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