00001
00016 #include "includes.h"
00017
00018 #include "common.h"
00019 #include "crypto.h"
00020 #include "asn1.h"
00021 #include "bignum.h"
00022 #include "rsa.h"
00023
00024
00025 struct crypto_rsa_key {
00026 int private_key;
00027 struct bignum *n;
00028 struct bignum *e;
00029
00030 struct bignum *d;
00031 struct bignum *p;
00032 struct bignum *q;
00033 struct bignum *dmp1;
00034 struct bignum *dmq1;
00035 struct bignum *iqmp;
00036 };
00037
00038
00039 static const u8 * crypto_rsa_parse_integer(const u8 *pos, const u8 *end,
00040 struct bignum *num)
00041 {
00042 struct asn1_hdr hdr;
00043
00044 if (pos == NULL)
00045 return NULL;
00046
00047 if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
00048 hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
00049 wpa_printf(MSG_DEBUG, "RSA: Expected INTEGER - found class %d "
00050 "tag 0x%x", hdr.class, hdr.tag);
00051 return NULL;
00052 }
00053
00054 if (bignum_set_unsigned_bin(num, hdr.payload, hdr.length) < 0) {
00055 wpa_printf(MSG_DEBUG, "RSA: Failed to parse INTEGER");
00056 return NULL;
00057 }
00058
00059 return hdr.payload + hdr.length;
00060 }
00061
00062
00070 struct crypto_rsa_key *
00071 crypto_rsa_import_public_key(const u8 *buf, size_t len)
00072 {
00073 struct crypto_rsa_key *key;
00074 struct asn1_hdr hdr;
00075 const u8 *pos, *end;
00076
00077 key = os_zalloc(sizeof(*key));
00078 if (key == NULL)
00079 return NULL;
00080
00081 key->n = bignum_init();
00082 key->e = bignum_init();
00083 if (key->n == NULL || key->e == NULL) {
00084 crypto_rsa_free(key);
00085 return NULL;
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 if (asn1_get_next(buf, len, &hdr) < 0 ||
00097 hdr.class != ASN1_CLASS_UNIVERSAL ||
00098 hdr.tag != ASN1_TAG_SEQUENCE) {
00099 wpa_printf(MSG_DEBUG, "RSA: Expected SEQUENCE "
00100 "(public key) - found class %d tag 0x%x",
00101 hdr.class, hdr.tag);
00102 goto error;
00103 }
00104 pos = hdr.payload;
00105 end = pos + hdr.length;
00106
00107 pos = crypto_rsa_parse_integer(pos, end, key->n);
00108 pos = crypto_rsa_parse_integer(pos, end, key->e);
00109
00110 if (pos == NULL)
00111 goto error;
00112
00113 if (pos != end) {
00114 wpa_hexdump(MSG_DEBUG,
00115 "RSA: Extra data in public key SEQUENCE",
00116 pos, end - pos);
00117 goto error;
00118 }
00119
00120 return key;
00121
00122 error:
00123 crypto_rsa_free(key);
00124 return NULL;
00125 }
00126
00127
00135 struct crypto_rsa_key *
00136 crypto_rsa_import_private_key(const u8 *buf, size_t len)
00137 {
00138 struct crypto_rsa_key *key;
00139 struct bignum *zero;
00140 struct asn1_hdr hdr;
00141 const u8 *pos, *end;
00142
00143 key = os_zalloc(sizeof(*key));
00144 if (key == NULL)
00145 return NULL;
00146
00147 key->private_key = 1;
00148
00149 key->n = bignum_init();
00150 key->e = bignum_init();
00151 key->d = bignum_init();
00152 key->p = bignum_init();
00153 key->q = bignum_init();
00154 key->dmp1 = bignum_init();
00155 key->dmq1 = bignum_init();
00156 key->iqmp = bignum_init();
00157
00158 if (key->n == NULL || key->e == NULL || key->d == NULL ||
00159 key->p == NULL || key->q == NULL || key->dmp1 == NULL ||
00160 key->dmq1 == NULL || key->iqmp == NULL) {
00161 crypto_rsa_free(key);
00162 return NULL;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 if (asn1_get_next(buf, len, &hdr) < 0 ||
00182 hdr.class != ASN1_CLASS_UNIVERSAL ||
00183 hdr.tag != ASN1_TAG_SEQUENCE) {
00184 wpa_printf(MSG_DEBUG, "RSA: Expected SEQUENCE "
00185 "(public key) - found class %d tag 0x%x",
00186 hdr.class, hdr.tag);
00187 goto error;
00188 }
00189 pos = hdr.payload;
00190 end = pos + hdr.length;
00191
00192 zero = bignum_init();
00193 if (zero == NULL)
00194 goto error;
00195 pos = crypto_rsa_parse_integer(pos, end, zero);
00196 if (pos == NULL || bignum_cmp_d(zero, 0) != 0) {
00197 wpa_printf(MSG_DEBUG, "RSA: Expected zero INTEGER in the "
00198 "beginning of private key; not found");
00199 bignum_deinit(zero);
00200 goto error;
00201 }
00202 bignum_deinit(zero);
00203
00204 pos = crypto_rsa_parse_integer(pos, end, key->n);
00205 pos = crypto_rsa_parse_integer(pos, end, key->e);
00206 pos = crypto_rsa_parse_integer(pos, end, key->d);
00207 pos = crypto_rsa_parse_integer(pos, end, key->p);
00208 pos = crypto_rsa_parse_integer(pos, end, key->q);
00209 pos = crypto_rsa_parse_integer(pos, end, key->dmp1);
00210 pos = crypto_rsa_parse_integer(pos, end, key->dmq1);
00211 pos = crypto_rsa_parse_integer(pos, end, key->iqmp);
00212
00213 if (pos == NULL)
00214 goto error;
00215
00216 if (pos != end) {
00217 wpa_hexdump(MSG_DEBUG,
00218 "RSA: Extra data in public key SEQUENCE",
00219 pos, end - pos);
00220 goto error;
00221 }
00222
00223 return key;
00224
00225 error:
00226 crypto_rsa_free(key);
00227 return NULL;
00228 }
00229
00230
00237 size_t crypto_rsa_get_modulus_len(struct crypto_rsa_key *key)
00238 {
00239 return bignum_get_unsigned_bin_len(key->n);
00240 }
00241
00242
00254 int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen,
00255 struct crypto_rsa_key *key, int use_private)
00256 {
00257 struct bignum *tmp, *a = NULL, *b = NULL;
00258 int ret = -1;
00259 size_t modlen;
00260
00261 if (use_private && !key->private_key)
00262 return -1;
00263
00264 tmp = bignum_init();
00265 if (tmp == NULL)
00266 return -1;
00267
00268 if (bignum_set_unsigned_bin(tmp, in, inlen) < 0)
00269 goto error;
00270 if (bignum_cmp(key->n, tmp) < 0) {
00271
00272 goto error;
00273 }
00274
00275 if (use_private) {
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 a = bignum_init();
00290 b = bignum_init();
00291 if (a == NULL || b == NULL)
00292 goto error;
00293
00294
00295 if (bignum_exptmod(tmp, key->dmp1, key->p, a) < 0)
00296 goto error;
00297
00298
00299 if (bignum_exptmod(tmp, key->dmq1, key->q, b) < 0)
00300 goto error;
00301
00302
00303 if (bignum_sub(a, b, tmp) < 0 ||
00304 bignum_mulmod(tmp, key->iqmp, key->p, tmp) < 0)
00305 goto error;
00306
00307
00308 if (bignum_mul(tmp, key->q, tmp) < 0 ||
00309 bignum_add(tmp, b, tmp) < 0)
00310 goto error;
00311 } else {
00312
00313
00314 if (bignum_exptmod(tmp, key->e, key->n, tmp) < 0)
00315 goto error;
00316 }
00317
00318 modlen = crypto_rsa_get_modulus_len(key);
00319 if (modlen > *outlen) {
00320 *outlen = modlen;
00321 goto error;
00322 }
00323
00324 if (bignum_get_unsigned_bin_len(tmp) > modlen)
00325 goto error;
00326
00327 *outlen = modlen;
00328 os_memset(out, 0, modlen);
00329 if (bignum_get_unsigned_bin(
00330 tmp, out +
00331 (modlen - bignum_get_unsigned_bin_len(tmp)), NULL) < 0)
00332 goto error;
00333
00334 ret = 0;
00335
00336 error:
00337 bignum_deinit(tmp);
00338 bignum_deinit(a);
00339 bignum_deinit(b);
00340 return ret;
00341 }
00342
00343
00352 void crypto_rsa_free(struct crypto_rsa_key *key)
00353 {
00354 if (key) {
00355 bignum_deinit(key->n);
00356 bignum_deinit(key->e);
00357 bignum_deinit(key->d);
00358 bignum_deinit(key->p);
00359 bignum_deinit(key->q);
00360 bignum_deinit(key->dmp1);
00361 bignum_deinit(key->dmq1);
00362 bignum_deinit(key->iqmp);
00363 os_free(key);
00364 }
00365 }
00366