1*8c0ef552Stb /* $OpenBSD: rsa_method_test.c,v 1.5 2025/01/05 18:21:36 tb Exp $ */ 20d1389ecStb 30d1389ecStb /* 40d1389ecStb * Copyright (c) 2025 Theo Buehler <tb@openbsd.org> 50d1389ecStb * 60d1389ecStb * Permission to use, copy, modify, and distribute this software for any 70d1389ecStb * purpose with or without fee is hereby granted, provided that the above 80d1389ecStb * copyright notice and this permission notice appear in all copies. 90d1389ecStb * 100d1389ecStb * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 110d1389ecStb * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 120d1389ecStb * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 130d1389ecStb * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 140d1389ecStb * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 150d1389ecStb * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 160d1389ecStb * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 170d1389ecStb */ 180d1389ecStb 190d1389ecStb #include <assert.h> 200d1389ecStb #include <err.h> 210d1389ecStb #include <stdint.h> 220d1389ecStb #include <stdio.h> 230d1389ecStb 240d1389ecStb #include <openssl/asn1.h> 250d1389ecStb #include <openssl/bn.h> 260d1389ecStb #include <openssl/err.h> 270d1389ecStb #include <openssl/evp.h> 280d1389ecStb #include <openssl/objects.h> 290d1389ecStb #include <openssl/rsa.h> 300d1389ecStb #include <openssl/x509.h> 310d1389ecStb 320d1389ecStb /* 330d1389ecStb * XXX - This currently only covers sign and verify. 340d1389ecStb */ 350d1389ecStb 360d1389ecStb /* sigh */ 370d1389ecStb static int ex_index; 380d1389ecStb 390d1389ecStb /* Unsure if this applies to RSA, ASN.1, or the OpenSSL code base altogether. */ 400d1389ecStb static const uint8_t msg[] = { 410d1389ecStb 0x44, 0x69, 0x65, 0x2c, 0x20, 0x64, 0x69, 0x65, 420d1389ecStb 0x2c, 0x20, 0x64, 0x69, 0x65, 0x2c, 0x20, 0x6d, 430d1389ecStb 0x79, 0x20, 0x64, 0x61, 0x72, 0x6c, 0x69, 0x6e, 440d1389ecStb 0x67, 0x0a, 0x44, 0x6f, 0x6e, 0x27, 0x74, 0x20, 450d1389ecStb 0x75, 0x74, 0x74, 0x65, 0x72, 0x20, 0x61, 0x20, 460d1389ecStb 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x77, 470d1389ecStb 0x6f, 0x72, 0x64, 0x0a, 0x44, 0x69, 0x65, 0x2c, 480d1389ecStb 0x20, 0x64, 0x69, 0x65, 0x2c, 0x20, 0x64, 0x69, 490d1389ecStb 0x65, 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x64, 0x61, 500d1389ecStb 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x0a, 0x53, 0x68, 510d1389ecStb 0x75, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 520d1389ecStb 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x20, 0x65, 530d1389ecStb 0x79, 0x65, 0x73, 0x0a, 0x0a, 0x49, 0x27, 0x6c, 540d1389ecStb 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 0x65, 550d1389ecStb 0x69, 0x6e, 0x67, 0x20, 0x79, 0x6f, 0x75, 0x20, 560d1389ecStb 0x61, 0x67, 0x61, 0x69, 0x6e, 0x0a, 0x49, 0x27, 570d1389ecStb 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 580d1389ecStb 0x65, 0x69, 0x6e, 0x67, 0x20, 0x79, 0x6f, 0x75, 590d1389ecStb 0x20, 0x69, 0x6e, 0x20, 0x68, 0x65, 0x6c, 0x6c, 600d1389ecStb 0x0a, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x4d, 0x69, 610d1389ecStb 0x73, 0x66, 0x69, 0x74, 0x73, 0x20, 0x7e, 0x20, 620d1389ecStb 0x31, 0x39, 0x38, 0x32, 630d1389ecStb }; 640d1389ecStb 650d1389ecStb static int 660d1389ecStb sign_and_verify(const char *descr, EVP_PKEY *priv, EVP_PKEY *pub) 670d1389ecStb { 680d1389ecStb ASN1_IA5STRING *message = NULL; 690d1389ecStb ASN1_BIT_STRING *signature = NULL; 700d1389ecStb X509_ALGOR *x509_alg = NULL; 710d1389ecStb const ASN1_OBJECT *oid; 720d1389ecStb int nid, ret; 730d1389ecStb int failed = 1; 740d1389ecStb 750d1389ecStb if ((message = ASN1_IA5STRING_new()) == NULL) 763af2523fStb errx(1, "%s: ASN1_IA5STRING_new", __func__); 770d1389ecStb if (!ASN1_STRING_set(message, msg, sizeof(msg))) 783af2523fStb errx(1, "%s: ASN1_STRING_set", __func__); 790d1389ecStb 800d1389ecStb if ((signature = ASN1_BIT_STRING_new()) == NULL) 813af2523fStb errx(1, "%s: ASN1_BIT_STRING_new", __func__); 820d1389ecStb if ((x509_alg = X509_ALGOR_new()) == NULL) 833af2523fStb errx(1, "%s: X509_ALGOR_new", __func__); 840d1389ecStb if ((ret = ASN1_item_sign(&ASN1_IA5STRING_it, x509_alg, NULL, signature, 850d1389ecStb message, priv, EVP_sha256())) <= 0) { 860d1389ecStb fprintf(stderr, "FAIL: %s (%s): ASN1_item_sign() returned %d\n", 870d1389ecStb __func__, descr, ret); 880d1389ecStb ERR_print_errors_fp(stderr); 890d1389ecStb goto err; 900d1389ecStb } 910d1389ecStb 920d1389ecStb X509_ALGOR_get0(&oid, NULL, NULL, x509_alg); 930d1389ecStb if ((nid = OBJ_obj2nid(oid)) != NID_sha256WithRSAEncryption) { 940d1389ecStb fprintf(stderr, "FAIL: %s (%s): OBJ_obj2nid(): want %d, got %d\n", 950d1389ecStb __func__, descr, NID_sha256WithRSAEncryption, nid); 960d1389ecStb goto err; 970d1389ecStb } 980d1389ecStb 990d1389ecStb if ((ret = ASN1_item_verify(&ASN1_IA5STRING_it, x509_alg, signature, 1000d1389ecStb message, pub)) != 1) { 1010d1389ecStb fprintf(stderr, "FAIL: %s (%s): ASN1_item_verify() returned %d\n", 1020d1389ecStb __func__, descr, ret); 1030d1389ecStb ERR_print_errors_fp(stderr); 1040d1389ecStb goto err; 1050d1389ecStb } 1060d1389ecStb 1070d1389ecStb failed = 0; 1080d1389ecStb 1090d1389ecStb err: 1100d1389ecStb ASN1_IA5STRING_free(message); 1110d1389ecStb ASN1_BIT_STRING_free(signature); 1120d1389ecStb X509_ALGOR_free(x509_alg); 1130d1389ecStb 1140d1389ecStb return failed; 1150d1389ecStb } 1160d1389ecStb 1170d1389ecStb static void 1180d1389ecStb generate_rsa_keypair(int bits, int exponent, RSA **out_priv, RSA **out_pub) 1190d1389ecStb { 1200d1389ecStb BIGNUM *e; 1210d1389ecStb RSA *rsa; 1220d1389ecStb 1230d1389ecStb assert(out_priv == NULL || *out_priv == NULL); 1240d1389ecStb assert(out_pub == NULL || *out_pub == NULL); 1250d1389ecStb 1260d1389ecStb if ((e = BN_new()) == NULL) 1270d1389ecStb errx(1, "%s: BN_new()", __func__); 1280d1389ecStb if (!BN_set_word(e, exponent)) 1290d1389ecStb errx(1, "%s: BN_set_word()", __func__); 1300d1389ecStb 1310d1389ecStb if ((rsa = RSA_new()) == NULL) 1320d1389ecStb errx(1, "%s: RSA_new()", __func__); 1330d1389ecStb if (!RSA_generate_key_ex(rsa, bits, e, NULL)) 1340d1389ecStb errx(1, "%s: RSA_generate_key_ex", __func__); 1350d1389ecStb 1360d1389ecStb /* Take the opportunity to exercise these two functions. */ 1370d1389ecStb if (out_priv != NULL) { 1380d1389ecStb if ((*out_priv = RSAPrivateKey_dup(rsa)) == NULL) 1390d1389ecStb errx(1, "%s: RSAPrivateKey_dup", __func__); 1400d1389ecStb } 1410d1389ecStb if (out_pub != NULL) { 1420d1389ecStb if ((*out_pub = RSAPublicKey_dup(rsa)) == NULL) 1430d1389ecStb errx(1, "%s: RSAPublicKey_dup", __func__); 1440d1389ecStb } 1450d1389ecStb 1460d1389ecStb RSA_free(rsa); 1470d1389ecStb BN_free(e); 1480d1389ecStb } 1490d1389ecStb 1500d1389ecStb static void 1510d1389ecStb rsa_to_evp(RSA *rsa, EVP_PKEY **out_evp) 1520d1389ecStb { 1530d1389ecStb assert(*out_evp == NULL); 1540d1389ecStb 1550d1389ecStb if ((*out_evp = EVP_PKEY_new()) == NULL) 1560d1389ecStb errx(1, "%s: EVP_PKEY_new", __func__); 1570d1389ecStb if (!EVP_PKEY_set1_RSA(*out_evp, rsa)) 1580d1389ecStb errx(1, "%s: EVP_PKEY_set1_RSA", __func__); 1590d1389ecStb } 1600d1389ecStb 1610d1389ecStb static void 1620d1389ecStb clear_evp_keys(EVP_PKEY **evp_priv, EVP_PKEY **evp_pub) 1630d1389ecStb { 1640d1389ecStb EVP_PKEY_free(*evp_priv); 1650d1389ecStb EVP_PKEY_free(*evp_pub); 1660d1389ecStb *evp_priv = NULL; 1670d1389ecStb *evp_pub = NULL; 1680d1389ecStb } 1690d1389ecStb 1700d1389ecStb static int 1710d1389ecStb rsa_method_app_data_sign(int dtype, const unsigned char *m, unsigned int m_len, 1720d1389ecStb unsigned char *sig, unsigned int *sig_len, const RSA *rsa) 1730d1389ecStb { 1740d1389ecStb const RSA_METHOD *method = RSA_get_method(rsa); 1750d1389ecStb RSA *sign_rsa = RSA_meth_get0_app_data(method); 1760d1389ecStb 1770d1389ecStb return RSA_sign(dtype, m, m_len, sig, sig_len, sign_rsa); 1780d1389ecStb } 1790d1389ecStb 1800d1389ecStb static int 1810d1389ecStb rsa_ex_data_verify(int dtype, const unsigned char *m, unsigned int m_len, 1820d1389ecStb const unsigned char *sig, unsigned int sig_len, const RSA *rsa) 1830d1389ecStb { 1840d1389ecStb RSA *verify_rsa; 1850d1389ecStb 1860d1389ecStb assert(ex_index != 0); 1870d1389ecStb 1880d1389ecStb if ((verify_rsa = RSA_get_ex_data(rsa, ex_index)) == NULL) 1890d1389ecStb errx(1, "%s: RSA_get_ex_data", __func__); 1900d1389ecStb 1910d1389ecStb return RSA_verify(dtype, m, m_len, sig, sig_len, verify_rsa); 1920d1389ecStb } 1930d1389ecStb 1940d1389ecStb static int 1950d1389ecStb sign_and_verify_test(void) 1960d1389ecStb { 1970d1389ecStb RSA_METHOD *sign_verify_method = NULL; 1980d1389ecStb RSA *rsa_priv = NULL, *rsa_pub = NULL, *rsa_bogus = NULL; 1990d1389ecStb EVP_PKEY *evp_priv = NULL, *evp_pub = NULL; 2000d1389ecStb int failed = 0; 2010d1389ecStb 2020d1389ecStb assert(ex_index != 0); 2030d1389ecStb 2040d1389ecStb /* 2050d1389ecStb * XXX - Hilarity ensues if the public key sizes don't match. 2060d1389ecStb * One reason is that EVP_PKEY_sign() uses EVP_PKEY_size() 2070d1389ecStb * which ignores the RSA method. Awesome design is awesome and 2080d1389ecStb * OpenSSL's abstractions are leakier than Manneken Pis. 2090d1389ecStb */ 2100d1389ecStb generate_rsa_keypair(2048, RSA_F4, &rsa_priv, &rsa_pub); 211*8c0ef552Stb generate_rsa_keypair(2048, RSA_3, NULL, &rsa_bogus); 2120d1389ecStb 2130d1389ecStb rsa_to_evp(rsa_priv, &evp_priv); 2140d1389ecStb rsa_to_evp(rsa_pub, &evp_pub); 2150d1389ecStb 2160d1389ecStb failed |= sign_and_verify("default method", evp_priv, evp_pub); 2170d1389ecStb 2180d1389ecStb clear_evp_keys(&evp_priv, &evp_pub); 2190d1389ecStb 2200d1389ecStb if (!RSA_set_ex_data(rsa_bogus, ex_index, rsa_pub)) 2210d1389ecStb errx(1, "%s: RSA_set_ex_data", __func__); 2220d1389ecStb 2230d1389ecStb if ((sign_verify_method = RSA_meth_dup(RSA_get_default_method())) == NULL) 2240d1389ecStb errx(1, "%s: RSA_get_default_method", __func__); 2250d1389ecStb if (!RSA_meth_set0_app_data(sign_verify_method, rsa_priv)) 2260d1389ecStb errx(1, "%s: RSA_meth_set0_app_data", __func__); 2270d1389ecStb 2280d1389ecStb if (!RSA_meth_set_sign(sign_verify_method, rsa_method_app_data_sign)) 2290d1389ecStb errx(1, "%s: RSA_meth_set_sign", __func__); 2300d1389ecStb if (!RSA_meth_set_verify(sign_verify_method, rsa_ex_data_verify)) 2310d1389ecStb errx(1, "%s: RSA_meth_set_verify", __func__); 2320d1389ecStb 2330d1389ecStb if (!RSA_set_method(rsa_bogus, sign_verify_method)) 2340d1389ecStb errx(1, "%s: RSA_set_method", __func__); 2350d1389ecStb 2360d1389ecStb rsa_to_evp(rsa_bogus, &evp_priv); 2370d1389ecStb rsa_to_evp(rsa_pub, &evp_pub); 2380d1389ecStb 2390d1389ecStb failed |= sign_and_verify("app data sign method", evp_priv, evp_pub); 2400d1389ecStb 2410d1389ecStb clear_evp_keys(&evp_priv, &evp_pub); 2420d1389ecStb 2430d1389ecStb rsa_to_evp(rsa_priv, &evp_priv); 2440d1389ecStb rsa_to_evp(rsa_bogus, &evp_pub); 2450d1389ecStb 2460d1389ecStb failed |= sign_and_verify("ex data verify method", evp_priv, evp_pub); 2470d1389ecStb 2480d1389ecStb clear_evp_keys(&evp_priv, &evp_pub); 2490d1389ecStb 2500d1389ecStb rsa_to_evp(rsa_bogus, &evp_priv); 2510d1389ecStb rsa_to_evp(rsa_bogus, &evp_pub); 2520d1389ecStb 253cd398615Stb failed |= sign_and_verify("both sides bogus", evp_priv, evp_pub); 2540d1389ecStb 2550d1389ecStb RSA_free(rsa_priv); 2560d1389ecStb RSA_free(rsa_pub); 2570d1389ecStb RSA_free(rsa_bogus); 2580d1389ecStb EVP_PKEY_free(evp_priv); 2590d1389ecStb EVP_PKEY_free(evp_pub); 2600d1389ecStb RSA_meth_free(sign_verify_method); 2610d1389ecStb 2620d1389ecStb return failed; 2630d1389ecStb } 2640d1389ecStb 2650d1389ecStb int 2660d1389ecStb main(void) 2670d1389ecStb { 2680d1389ecStb int failed = 0; 2690d1389ecStb 2700d1389ecStb if ((ex_index = RSA_get_ex_new_index(0, NULL, NULL, NULL, NULL)) <= 0) 2710d1389ecStb errx(1, "RSA_get_ex_new_index"); 2720d1389ecStb 2730d1389ecStb failed |= sign_and_verify_test(); 2740d1389ecStb 2750d1389ecStb return failed; 2760d1389ecStb } 277