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