1 #include <assert.h>
2 #include <stddef.h>
3
4 #include <openssl/bn.h>
5 #include <openssl/err.h>
6 #include <openssl/opensslv.h>
7 #include <openssl/rsa.h>
8
9 #include "warnp.h"
10
11 #include "crypto_compat.h"
12
13 #ifndef OPENSSL_VERSION_NUMBER
14 #error "OPENSSL_VERSION_NUMBER must be defined"
15 #endif
16
17 /*
18 * LibreSSL claims to be OpenSSL 2.0, but (currently) has APIs compatible with
19 * OpenSSL 1.0.1g.
20 */
21 #ifdef LIBRESSL_VERSION_NUMBER
22 #undef OPENSSL_VERSION_NUMBER
23 #define OPENSSL_VERSION_NUMBER 0x1000107fL
24 #endif
25
26 /**
27 * crypto_compat_RSA_valid_size(rsa):
28 * Return nonzero if ${rsa} has a valid size, and zero for an invalid size.
29 */
30 int
crypto_compat_RSA_valid_size(const RSA * const rsa)31 crypto_compat_RSA_valid_size(const RSA * const rsa)
32 {
33
34 /* Sanity checks. */
35 assert(rsa != NULL);
36
37 #if OPENSSL_VERSION_NUMBER < 0x10100000L
38 assert(rsa->n != NULL);
39 return ((RSA_size(rsa) == 256) && (BN_num_bits(rsa->n) == 2048));
40 #else
41 return ((RSA_size(rsa) == 256) && (RSA_bits(rsa) == 2048));
42 #endif
43 }
44
45 /**
46 * crypto_compat_RSA_import(key, n, e, d, p, q, dmp1, dmq1, iqmp):
47 * Import the given BIGNUMs into the RSA ${key}.
48 */
49 int
crypto_compat_RSA_import(RSA ** key,BIGNUM * n,BIGNUM * e,BIGNUM * d,BIGNUM * p,BIGNUM * q,BIGNUM * dmp1,BIGNUM * dmq1,BIGNUM * iqmp)50 crypto_compat_RSA_import(RSA ** key, BIGNUM * n, BIGNUM * e, BIGNUM * d,
51 BIGNUM * p, BIGNUM * q, BIGNUM * dmp1, BIGNUM * dmq1, BIGNUM * iqmp)
52 {
53
54 /* Sanity checks. */
55 assert(key != NULL);
56 assert((n != NULL) && (e != NULL));
57
58 /* All the private-key-related variables are NULL, or they're not. */
59 if (d == NULL) {
60 assert((p == NULL) && (q == NULL) && (dmp1 == NULL)
61 && (dmq1 == NULL) && (iqmp == NULL));
62 } else {
63 assert((p != NULL) && (q != NULL) && (dmp1 != NULL)
64 && (dmq1 != NULL) && (iqmp != NULL));
65 }
66
67 /* Put values into RSA key. */
68 #if OPENSSL_VERSION_NUMBER < 0x10100000L
69 (*key)->n = n;
70 (*key)->e = e;
71 if (d != NULL) {
72 /* Private key. */
73 (*key)->d = d;
74 (*key)->p = p;
75 (*key)->q = q;
76 (*key)->dmp1 = dmp1;
77 (*key)->dmq1 = dmq1;
78 (*key)->iqmp = iqmp;
79 }
80 #else
81 /* Do we have a public key, or private key? */
82 if (d == NULL) {
83 /* We could use d here, but using NULL makes it more clear. */
84 if (RSA_set0_key(*key, n, e, NULL) != 1)
85 goto err0;
86 } else {
87 /* Private key. */
88 if (RSA_set0_key(*key, n, e, d) != 1)
89 goto err0;
90 if (RSA_set0_factors(*key, p, q) != 1)
91 goto err0;
92 if (RSA_set0_crt_params(*key, dmp1, dmq1, iqmp) != 1)
93 goto err0;
94 }
95 #endif
96
97 /* Success! */
98 return (0);
99
100 #if OPENSSL_VERSION_NUMBER < 0x10100000L
101 #else
102 err0:
103 /* Failure! */
104 return (-1);
105 #endif
106 }
107
108 /**
109 * crypto_compat_RSA_export(key, n, e, d, p, q, dmp1, dmq1, iqmp):
110 * Export values from the given RSA ${key} into the BIGNUMs. ${n} and ${e}
111 * must be non-NULL; the other values may be NULL if desired, and will
112 * therefore not be exported.
113 */
114 int
crypto_compat_RSA_export(RSA * key,const BIGNUM ** n,const BIGNUM ** e,const BIGNUM ** d,const BIGNUM ** p,const BIGNUM ** q,const BIGNUM ** dmp1,const BIGNUM ** dmq1,const BIGNUM ** iqmp)115 crypto_compat_RSA_export(RSA * key, const BIGNUM ** n, const BIGNUM ** e,
116 const BIGNUM ** d, const BIGNUM ** p, const BIGNUM ** q,
117 const BIGNUM ** dmp1, const BIGNUM ** dmq1, const BIGNUM ** iqmp)
118 {
119
120 /* Sanity checks. */
121 assert(key != NULL);
122 assert((n != NULL) && (e != NULL));
123
124 /* All the private-key-related variables are NULL, or they're not. */
125 if (d == NULL) {
126 assert((p == NULL) && (q == NULL) && (dmp1 == NULL)
127 && (dmq1 == NULL) && (iqmp == NULL));
128 } else {
129 assert((p != NULL) && (q != NULL) && (dmp1 != NULL)
130 && (dmq1 != NULL) && (iqmp != NULL));
131 }
132
133 /* Get values from RSA key. */
134 #if OPENSSL_VERSION_NUMBER < 0x10100000L
135 *n = key->n;
136 *e = key->e;
137 if (d != NULL) {
138 /* Private key. */
139 *d = key->d;
140 *p = key->p;
141 *q = key->q;
142 *dmp1 = key->dmp1;
143 *dmq1 = key->dmq1;
144 *iqmp = key->iqmp;
145 }
146 #else
147 /* Do we have a public key, or private key? */
148 if (d == NULL) {
149 /* We could use d here, but using NULL makes it more clear. */
150 RSA_get0_key(key, n, e, NULL);
151 } else {
152 /* Private key. */
153 RSA_get0_key(key, n, e, d);
154 RSA_get0_factors(key, p, q);
155 RSA_get0_crt_params(key, dmp1, dmq1, iqmp);
156 }
157 #endif
158
159 /* Success! */
160 return (0);
161 }
162
163 /**
164 * crypto_compat_RSA_generate_key():
165 * Generate a key pair.
166 */
167 RSA *
crypto_compat_RSA_generate_key()168 crypto_compat_RSA_generate_key()
169 {
170 RSA * key;
171
172 #if OPENSSL_VERSION_NUMBER < 0x00908000L
173 /* Generate key. */
174 if ((key = RSA_generate_key(2048, 65537, NULL, NULL)) == NULL) {
175 warn0("%s", ERR_error_string(ERR_get_error(), NULL));
176 goto err0;
177 }
178
179 /* Success! */
180 return (key);
181 #else
182 BIGNUM * e;
183
184 /* Set up parameter. */
185 if ((e = BN_new()) == NULL) {
186 warn0("%s", ERR_error_string(ERR_get_error(), NULL));
187 goto err0;
188 }
189 BN_set_word(e, 65537);
190
191 /* Generate key. */
192 if ((key = RSA_new()) == NULL) {
193 warn0("%s", ERR_error_string(ERR_get_error(), NULL));
194 goto err1;
195 }
196 if (RSA_generate_key_ex(key, 2048, e, NULL) != 1) {
197 warn0("%s", ERR_error_string(ERR_get_error(), NULL));
198 goto err2;
199 }
200
201 /* Clean up. */
202 BN_free(e);
203
204 /* Success! */
205 return (key);
206
207 err2:
208 RSA_free(key);
209 err1:
210 BN_free(e);
211 #endif
212 err0:
213 /* Failure! */
214 return (NULL);
215 }
216