1*0d1389ecStb /* $OpenBSD: rsa_method_test.c,v 1.1 2025/01/04 18:16:37 tb Exp $ */ 2*0d1389ecStb 3*0d1389ecStb /* 4*0d1389ecStb * Copyright (c) 2025 Theo Buehler <tb@openbsd.org> 5*0d1389ecStb * 6*0d1389ecStb * Permission to use, copy, modify, and distribute this software for any 7*0d1389ecStb * purpose with or without fee is hereby granted, provided that the above 8*0d1389ecStb * copyright notice and this permission notice appear in all copies. 9*0d1389ecStb * 10*0d1389ecStb * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11*0d1389ecStb * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12*0d1389ecStb * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13*0d1389ecStb * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14*0d1389ecStb * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15*0d1389ecStb * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16*0d1389ecStb * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17*0d1389ecStb */ 18*0d1389ecStb 19*0d1389ecStb #include <assert.h> 20*0d1389ecStb #include <err.h> 21*0d1389ecStb #include <stdint.h> 22*0d1389ecStb #include <stdio.h> 23*0d1389ecStb 24*0d1389ecStb #include <openssl/asn1.h> 25*0d1389ecStb #include <openssl/bn.h> 26*0d1389ecStb #include <openssl/err.h> 27*0d1389ecStb #include <openssl/evp.h> 28*0d1389ecStb #include <openssl/objects.h> 29*0d1389ecStb #include <openssl/rsa.h> 30*0d1389ecStb #include <openssl/x509.h> 31*0d1389ecStb 32*0d1389ecStb /* 33*0d1389ecStb * XXX - This currently only covers sign and verify. 34*0d1389ecStb */ 35*0d1389ecStb 36*0d1389ecStb /* sigh */ 37*0d1389ecStb static int ex_index; 38*0d1389ecStb 39*0d1389ecStb /* Unsure if this applies to RSA, ASN.1, or the OpenSSL code base altogether. */ 40*0d1389ecStb static const uint8_t msg[] = { 41*0d1389ecStb 0x44, 0x69, 0x65, 0x2c, 0x20, 0x64, 0x69, 0x65, 42*0d1389ecStb 0x2c, 0x20, 0x64, 0x69, 0x65, 0x2c, 0x20, 0x6d, 43*0d1389ecStb 0x79, 0x20, 0x64, 0x61, 0x72, 0x6c, 0x69, 0x6e, 44*0d1389ecStb 0x67, 0x0a, 0x44, 0x6f, 0x6e, 0x27, 0x74, 0x20, 45*0d1389ecStb 0x75, 0x74, 0x74, 0x65, 0x72, 0x20, 0x61, 0x20, 46*0d1389ecStb 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x77, 47*0d1389ecStb 0x6f, 0x72, 0x64, 0x0a, 0x44, 0x69, 0x65, 0x2c, 48*0d1389ecStb 0x20, 0x64, 0x69, 0x65, 0x2c, 0x20, 0x64, 0x69, 49*0d1389ecStb 0x65, 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x64, 0x61, 50*0d1389ecStb 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x0a, 0x53, 0x68, 51*0d1389ecStb 0x75, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 52*0d1389ecStb 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x20, 0x65, 53*0d1389ecStb 0x79, 0x65, 0x73, 0x0a, 0x0a, 0x49, 0x27, 0x6c, 54*0d1389ecStb 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 0x65, 55*0d1389ecStb 0x69, 0x6e, 0x67, 0x20, 0x79, 0x6f, 0x75, 0x20, 56*0d1389ecStb 0x61, 0x67, 0x61, 0x69, 0x6e, 0x0a, 0x49, 0x27, 57*0d1389ecStb 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 58*0d1389ecStb 0x65, 0x69, 0x6e, 0x67, 0x20, 0x79, 0x6f, 0x75, 59*0d1389ecStb 0x20, 0x69, 0x6e, 0x20, 0x68, 0x65, 0x6c, 0x6c, 60*0d1389ecStb 0x0a, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x4d, 0x69, 61*0d1389ecStb 0x73, 0x66, 0x69, 0x74, 0x73, 0x20, 0x7e, 0x20, 62*0d1389ecStb 0x31, 0x39, 0x38, 0x32, 63*0d1389ecStb }; 64*0d1389ecStb 65*0d1389ecStb static int 66*0d1389ecStb sign_and_verify(const char *descr, EVP_PKEY *priv, EVP_PKEY *pub) 67*0d1389ecStb { 68*0d1389ecStb ASN1_IA5STRING *message = NULL; 69*0d1389ecStb ASN1_BIT_STRING *signature = NULL; 70*0d1389ecStb X509_ALGOR *x509_alg = NULL; 71*0d1389ecStb const ASN1_OBJECT *oid; 72*0d1389ecStb int nid, ret; 73*0d1389ecStb int failed = 1; 74*0d1389ecStb 75*0d1389ecStb if ((message = ASN1_IA5STRING_new()) == NULL) 76*0d1389ecStb errx(1, "ASN1_IA5STRING_new"); 77*0d1389ecStb if (!ASN1_STRING_set(message, msg, sizeof(msg))) 78*0d1389ecStb errx(1, "ASN1_STRING_set"); 79*0d1389ecStb 80*0d1389ecStb if ((signature = ASN1_BIT_STRING_new()) == NULL) 81*0d1389ecStb errx(1, "ASN1_BIT_STRING_new"); 82*0d1389ecStb if ((x509_alg = X509_ALGOR_new()) == NULL) 83*0d1389ecStb errx(1, "X509_ALGOR_new"); 84*0d1389ecStb if ((ret = ASN1_item_sign(&ASN1_IA5STRING_it, x509_alg, NULL, signature, 85*0d1389ecStb message, priv, EVP_sha256())) <= 0) { 86*0d1389ecStb fprintf(stderr, "FAIL: %s (%s): ASN1_item_sign() returned %d\n", 87*0d1389ecStb __func__, descr, ret); 88*0d1389ecStb ERR_print_errors_fp(stderr); 89*0d1389ecStb goto err; 90*0d1389ecStb } 91*0d1389ecStb 92*0d1389ecStb X509_ALGOR_get0(&oid, NULL, NULL, x509_alg); 93*0d1389ecStb if ((nid = OBJ_obj2nid(oid)) != NID_sha256WithRSAEncryption) { 94*0d1389ecStb fprintf(stderr, "FAIL: %s (%s): OBJ_obj2nid(): want %d, got %d\n", 95*0d1389ecStb __func__, descr, NID_sha256WithRSAEncryption, nid); 96*0d1389ecStb goto err; 97*0d1389ecStb } 98*0d1389ecStb 99*0d1389ecStb if ((ret = ASN1_item_verify(&ASN1_IA5STRING_it, x509_alg, signature, 100*0d1389ecStb message, pub)) != 1) { 101*0d1389ecStb fprintf(stderr, "FAIL: %s (%s): ASN1_item_verify() returned %d\n", 102*0d1389ecStb __func__, descr, ret); 103*0d1389ecStb ERR_print_errors_fp(stderr); 104*0d1389ecStb goto err; 105*0d1389ecStb } 106*0d1389ecStb 107*0d1389ecStb failed = 0; 108*0d1389ecStb 109*0d1389ecStb err: 110*0d1389ecStb ASN1_IA5STRING_free(message); 111*0d1389ecStb ASN1_BIT_STRING_free(signature); 112*0d1389ecStb X509_ALGOR_free(x509_alg); 113*0d1389ecStb 114*0d1389ecStb return failed; 115*0d1389ecStb } 116*0d1389ecStb 117*0d1389ecStb static void 118*0d1389ecStb generate_rsa_keypair(int bits, int exponent, RSA **out_priv, RSA **out_pub) 119*0d1389ecStb { 120*0d1389ecStb BIGNUM *e; 121*0d1389ecStb RSA *rsa; 122*0d1389ecStb 123*0d1389ecStb assert(out_priv == NULL || *out_priv == NULL); 124*0d1389ecStb assert(out_pub == NULL || *out_pub == NULL); 125*0d1389ecStb 126*0d1389ecStb if ((e = BN_new()) == NULL) 127*0d1389ecStb errx(1, "%s: BN_new()", __func__); 128*0d1389ecStb if (!BN_set_word(e, exponent)) 129*0d1389ecStb errx(1, "%s: BN_set_word()", __func__); 130*0d1389ecStb 131*0d1389ecStb if ((rsa = RSA_new()) == NULL) 132*0d1389ecStb errx(1, "%s: RSA_new()", __func__); 133*0d1389ecStb if (!RSA_generate_key_ex(rsa, bits, e, NULL)) 134*0d1389ecStb errx(1, "%s: RSA_generate_key_ex", __func__); 135*0d1389ecStb 136*0d1389ecStb /* Take the opportunity to exercise these two functions. */ 137*0d1389ecStb if (out_priv != NULL) { 138*0d1389ecStb if ((*out_priv = RSAPrivateKey_dup(rsa)) == NULL) 139*0d1389ecStb errx(1, "%s: RSAPrivateKey_dup", __func__); 140*0d1389ecStb } 141*0d1389ecStb if (out_pub != NULL) { 142*0d1389ecStb if ((*out_pub = RSAPublicKey_dup(rsa)) == NULL) 143*0d1389ecStb errx(1, "%s: RSAPublicKey_dup", __func__); 144*0d1389ecStb } 145*0d1389ecStb 146*0d1389ecStb RSA_free(rsa); 147*0d1389ecStb BN_free(e); 148*0d1389ecStb } 149*0d1389ecStb 150*0d1389ecStb static void 151*0d1389ecStb rsa_to_evp(RSA *rsa, EVP_PKEY **out_evp) 152*0d1389ecStb { 153*0d1389ecStb assert(*out_evp == NULL); 154*0d1389ecStb 155*0d1389ecStb if ((*out_evp = EVP_PKEY_new()) == NULL) 156*0d1389ecStb errx(1, "%s: EVP_PKEY_new", __func__); 157*0d1389ecStb if (!EVP_PKEY_set1_RSA(*out_evp, rsa)) 158*0d1389ecStb errx(1, "%s: EVP_PKEY_set1_RSA", __func__); 159*0d1389ecStb } 160*0d1389ecStb 161*0d1389ecStb static void 162*0d1389ecStb clear_evp_keys(EVP_PKEY **evp_priv, EVP_PKEY **evp_pub) 163*0d1389ecStb { 164*0d1389ecStb EVP_PKEY_free(*evp_priv); 165*0d1389ecStb EVP_PKEY_free(*evp_pub); 166*0d1389ecStb *evp_priv = NULL; 167*0d1389ecStb *evp_pub = NULL; 168*0d1389ecStb } 169*0d1389ecStb 170*0d1389ecStb static int 171*0d1389ecStb rsa_method_app_data_sign(int dtype, const unsigned char *m, unsigned int m_len, 172*0d1389ecStb unsigned char *sig, unsigned int *sig_len, const RSA *rsa) 173*0d1389ecStb { 174*0d1389ecStb const RSA_METHOD *method = RSA_get_method(rsa); 175*0d1389ecStb RSA *sign_rsa = RSA_meth_get0_app_data(method); 176*0d1389ecStb 177*0d1389ecStb return RSA_sign(dtype, m, m_len, sig, sig_len, sign_rsa); 178*0d1389ecStb } 179*0d1389ecStb 180*0d1389ecStb static int 181*0d1389ecStb rsa_ex_data_verify(int dtype, const unsigned char *m, unsigned int m_len, 182*0d1389ecStb const unsigned char *sig, unsigned int sig_len, const RSA *rsa) 183*0d1389ecStb { 184*0d1389ecStb RSA *verify_rsa; 185*0d1389ecStb 186*0d1389ecStb assert(ex_index != 0); 187*0d1389ecStb 188*0d1389ecStb if ((verify_rsa = RSA_get_ex_data(rsa, ex_index)) == NULL) 189*0d1389ecStb errx(1, "%s: RSA_get_ex_data", __func__); 190*0d1389ecStb 191*0d1389ecStb return RSA_verify(dtype, m, m_len, sig, sig_len, verify_rsa); 192*0d1389ecStb } 193*0d1389ecStb 194*0d1389ecStb static int 195*0d1389ecStb sign_and_verify_test(void) 196*0d1389ecStb { 197*0d1389ecStb RSA_METHOD *sign_verify_method = NULL; 198*0d1389ecStb RSA *rsa_priv = NULL, *rsa_pub = NULL, *rsa_bogus = NULL; 199*0d1389ecStb EVP_PKEY *evp_priv = NULL, *evp_pub = NULL; 200*0d1389ecStb int failed = 0; 201*0d1389ecStb 202*0d1389ecStb assert(ex_index != 0); 203*0d1389ecStb 204*0d1389ecStb /* 205*0d1389ecStb * XXX - Hilarity ensues if the public key sizes don't match. 206*0d1389ecStb * One reason is that EVP_PKEY_sign() uses EVP_PKEY_size() 207*0d1389ecStb * which ignores the RSA method. Awesome design is awesome and 208*0d1389ecStb * OpenSSL's abstractions are leakier than Manneken Pis. 209*0d1389ecStb */ 210*0d1389ecStb generate_rsa_keypair(2048, RSA_F4, &rsa_priv, &rsa_pub); 211*0d1389ecStb generate_rsa_keypair(2048, 3, NULL, &rsa_bogus); 212*0d1389ecStb 213*0d1389ecStb rsa_to_evp(rsa_priv, &evp_priv); 214*0d1389ecStb rsa_to_evp(rsa_pub, &evp_pub); 215*0d1389ecStb 216*0d1389ecStb failed |= sign_and_verify("default method", evp_priv, evp_pub); 217*0d1389ecStb 218*0d1389ecStb clear_evp_keys(&evp_priv, &evp_pub); 219*0d1389ecStb 220*0d1389ecStb 221*0d1389ecStb if (!RSA_set_ex_data(rsa_bogus, ex_index, rsa_pub)) 222*0d1389ecStb errx(1, "%s: RSA_set_ex_data", __func__); 223*0d1389ecStb 224*0d1389ecStb if ((sign_verify_method = RSA_meth_dup(RSA_get_default_method())) == NULL) 225*0d1389ecStb errx(1, "%s: RSA_get_default_method", __func__); 226*0d1389ecStb if (!RSA_meth_set0_app_data(sign_verify_method, rsa_priv)) 227*0d1389ecStb errx(1, "%s: RSA_meth_set0_app_data", __func__); 228*0d1389ecStb 229*0d1389ecStb if (!RSA_meth_set_sign(sign_verify_method, rsa_method_app_data_sign)) 230*0d1389ecStb errx(1, "%s: RSA_meth_set_sign", __func__); 231*0d1389ecStb if (!RSA_meth_set_verify(sign_verify_method, rsa_ex_data_verify)) 232*0d1389ecStb errx(1, "%s: RSA_meth_set_verify", __func__); 233*0d1389ecStb 234*0d1389ecStb RSA_set_flags(rsa_bogus, RSA_FLAG_SIGN_VER); 235*0d1389ecStb if (!RSA_set_method(rsa_bogus, sign_verify_method)) 236*0d1389ecStb errx(1, "%s: RSA_set_method", __func__); 237*0d1389ecStb 238*0d1389ecStb rsa_to_evp(rsa_bogus, &evp_priv); 239*0d1389ecStb rsa_to_evp(rsa_pub, &evp_pub); 240*0d1389ecStb 241*0d1389ecStb failed |= sign_and_verify("app data sign method", evp_priv, evp_pub); 242*0d1389ecStb 243*0d1389ecStb clear_evp_keys(&evp_priv, &evp_pub); 244*0d1389ecStb 245*0d1389ecStb rsa_to_evp(rsa_priv, &evp_priv); 246*0d1389ecStb rsa_to_evp(rsa_bogus, &evp_pub); 247*0d1389ecStb 248*0d1389ecStb failed |= sign_and_verify("ex data verify method", evp_priv, evp_pub); 249*0d1389ecStb 250*0d1389ecStb clear_evp_keys(&evp_priv, &evp_pub); 251*0d1389ecStb 252*0d1389ecStb rsa_to_evp(rsa_bogus, &evp_priv); 253*0d1389ecStb rsa_to_evp(rsa_bogus, &evp_pub); 254*0d1389ecStb 255*0d1389ecStb failed |= sign_and_verify("both sides bous", evp_priv, evp_pub); 256*0d1389ecStb 257*0d1389ecStb RSA_free(rsa_priv); 258*0d1389ecStb RSA_free(rsa_pub); 259*0d1389ecStb RSA_free(rsa_bogus); 260*0d1389ecStb EVP_PKEY_free(evp_priv); 261*0d1389ecStb EVP_PKEY_free(evp_pub); 262*0d1389ecStb RSA_meth_free(sign_verify_method); 263*0d1389ecStb 264*0d1389ecStb return failed; 265*0d1389ecStb } 266*0d1389ecStb 267*0d1389ecStb int 268*0d1389ecStb main(void) 269*0d1389ecStb { 270*0d1389ecStb int failed = 0; 271*0d1389ecStb 272*0d1389ecStb if ((ex_index = RSA_get_ex_new_index(0, NULL, NULL, NULL, NULL)) <= 0) 273*0d1389ecStb errx(1, "RSA_get_ex_new_index"); 274*0d1389ecStb 275*0d1389ecStb failed |= sign_and_verify_test(); 276*0d1389ecStb 277*0d1389ecStb return failed; 278*0d1389ecStb } 279