rsa.c

Go to the documentation of this file.
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; /* whether private key is set */
00027         struct bignum *n; /* modulus (p * q) */
00028         struct bignum *e; /* public exponent */
00029         /* The following parameters are available only if private_key is set */
00030         struct bignum *d; /* private exponent */
00031         struct bignum *p; /* prime p (factor of n) */
00032         struct bignum *q; /* prime q (factor of n) */
00033         struct bignum *dmp1; /* d mod (p - 1); CRT exponent */
00034         struct bignum *dmq1; /* d mod (q - 1); CRT exponent */
00035         struct bignum *iqmp; /* 1 / q mod p; CRT coefficient */
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          * PKCS #1, 7.1:
00091          * RSAPublicKey ::= SEQUENCE {
00092          *     modulus INTEGER, -- n
00093          *     publicExponent INTEGER -- e 
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          * PKCS #1, 7.2:
00168          * RSAPrivateKey ::= SEQUENCE {
00169          *    version Version,
00170          *    modulus INTEGER, -- n
00171          *    publicExponent INTEGER, -- e
00172          *    privateExponent INTEGER, -- d
00173          *    prime1 INTEGER, -- p
00174          *    prime2 INTEGER, -- q
00175          *    exponent1 INTEGER, -- d mod (p-1)
00176          *    exponent2 INTEGER, -- d mod (q-1)
00177          *    coefficient INTEGER -- (inverse of q) mod p
00178          * }
00179          *
00180          * Version ::= INTEGER -- shall be 0 for this version of the standard
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 /* EAP_TLS_FUNCS */
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                 /* Too large input value for the RSA key modulus */
00274                 goto error;
00275         }
00276 
00277         if (use_private) {
00278                 /*
00279                  * Decrypt (or sign) using Chinese remainer theorem to speed
00280                  * up calculation. This is equivalent to tmp = tmp^d mod n
00281                  * (which would require more CPU to calculate directly).
00282                  *
00283                  * dmp1 = (1/e) mod (p-1)
00284                  * dmq1 = (1/e) mod (q-1)
00285                  * iqmp = (1/q) mod p, where p > q
00286                  * m1 = c^dmp1 mod p
00287                  * m2 = c^dmq1 mod q
00288                  * h = q^-1 (m1 - m2) mod p
00289                  * m = m2 + hq
00290                  */
00291                 a = bignum_init();
00292                 b = bignum_init();
00293                 if (a == NULL || b == NULL)
00294                         goto error;
00295 
00296                 /* a = tmp^dmp1 mod p */
00297                 if (bignum_exptmod(tmp, key->dmp1, key->p, a) < 0)
00298                         goto error;
00299 
00300                 /* b = tmp^dmq1 mod q */
00301                 if (bignum_exptmod(tmp, key->dmq1, key->q, b) < 0)
00302                         goto error;
00303 
00304                 /* tmp = (a - b) * (1/q mod p) (mod p) */
00305                 if (bignum_sub(a, b, tmp) < 0 ||
00306                     bignum_mulmod(tmp, key->iqmp, key->p, tmp) < 0)
00307                         goto error;
00308 
00309                 /* tmp = b + q * tmp */
00310                 if (bignum_mul(tmp, key->q, tmp) < 0 ||
00311                     bignum_add(tmp, b, tmp) < 0)
00312                         goto error;
00313         } else {
00314                 /* Encrypt (or verify signature) */
00315                 /* tmp = tmp^e mod N */
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; /* should never happen */
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:53 2009 for hostapd by  doxygen 1.6.1