xref: /openbsd-src/regress/lib/libcrypto/rsa/rsa_method_test.c (revision 8c0ef5529f7d57aeee5bacadf4c844a997adf7f7)
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