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 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          * PKCS #1, 7.1:
00090          * RSAPublicKey ::= SEQUENCE {
00091          *     modulus INTEGER, -- n
00092          *     publicExponent INTEGER -- e 
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          * PKCS #1, 7.2:
00167          * RSAPrivateKey ::= SEQUENCE {
00168          *    version Version,
00169          *    modulus INTEGER, -- n
00170          *    publicExponent INTEGER, -- e
00171          *    privateExponent INTEGER, -- d
00172          *    prime1 INTEGER, -- p
00173          *    prime2 INTEGER, -- q
00174          *    exponent1 INTEGER, -- d mod (p-1)
00175          *    exponent2 INTEGER, -- d mod (q-1)
00176          *    coefficient INTEGER -- (inverse of q) mod p
00177          * }
00178          *
00179          * Version ::= INTEGER -- shall be 0 for this version of the standard
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                 /* Too large input value for the RSA key modulus */
00272                 goto error;
00273         }
00274 
00275         if (use_private) {
00276                 /*
00277                  * Decrypt (or sign) using Chinese remainer theorem to speed
00278                  * up calculation. This is equivalent to tmp = tmp^d mod n
00279                  * (which would require more CPU to calculate directly).
00280                  *
00281                  * dmp1 = (1/e) mod (p-1)
00282                  * dmq1 = (1/e) mod (q-1)
00283                  * iqmp = (1/q) mod p, where p > q
00284                  * m1 = c^dmp1 mod p
00285                  * m2 = c^dmq1 mod q
00286                  * h = q^-1 (m1 - m2) mod p
00287                  * m = m2 + hq
00288                  */
00289                 a = bignum_init();
00290                 b = bignum_init();
00291                 if (a == NULL || b == NULL)
00292                         goto error;
00293 
00294                 /* a = tmp^dmp1 mod p */
00295                 if (bignum_exptmod(tmp, key->dmp1, key->p, a) < 0)
00296                         goto error;
00297 
00298                 /* b = tmp^dmq1 mod q */
00299                 if (bignum_exptmod(tmp, key->dmq1, key->q, b) < 0)
00300                         goto error;
00301 
00302                 /* tmp = (a - b) * (1/q mod p) (mod p) */
00303                 if (bignum_sub(a, b, tmp) < 0 ||
00304                     bignum_mulmod(tmp, key->iqmp, key->p, tmp) < 0)
00305                         goto error;
00306 
00307                 /* tmp = b + q * tmp */
00308                 if (bignum_mul(tmp, key->q, tmp) < 0 ||
00309                     bignum_add(tmp, b, tmp) < 0)
00310                         goto error;
00311         } else {
00312                 /* Encrypt (or verify signature) */
00313                 /* tmp = tmp^e mod N */
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; /* should never happen */
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 

Generated on Sun Dec 31 13:48:55 2006 for wpa_supplicant by  doxygen 1.4.2