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