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