]> pd.if.org Git - zpackage/blob - libtomcrypt/src/pk/rsa/rsa_exptmod.c
commit files needed for zpm-fetchurl
[zpackage] / libtomcrypt / src / pk / rsa / rsa_exptmod.c
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2  *
3  * LibTomCrypt is a library that provides various cryptographic
4  * algorithms in a highly modular and flexible manner.
5  *
6  * The library is free for all purposes without any express
7  * guarantee it works.
8  */
9 #include "tomcrypt.h"
10
11 /**
12   @file rsa_exptmod.c
13   RSA PKCS exptmod, Tom St Denis
14   Added RSA blinding --nmav
15 */
16
17 #ifdef LTC_MRSA
18
19 /**
20    Compute an RSA modular exponentiation
21    @param in         The input data to send into RSA
22    @param inlen      The length of the input (octets)
23    @param out        [out] The destination
24    @param outlen     [in/out] The max size and resulting size of the output
25    @param which      Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC
26    @param key        The RSA key to use
27    @return CRYPT_OK if successful
28 */
29 int rsa_exptmod(const unsigned char *in,   unsigned long inlen,
30                       unsigned char *out,  unsigned long *outlen, int which,
31                       rsa_key *key)
32 {
33    void        *tmp, *tmpa, *tmpb;
34    #ifdef LTC_RSA_BLINDING
35    void        *rnd, *rndi /* inverse of rnd */;
36    #endif
37    unsigned long x;
38    int           err, has_crt_parameters;
39
40    LTC_ARGCHK(in     != NULL);
41    LTC_ARGCHK(out    != NULL);
42    LTC_ARGCHK(outlen != NULL);
43    LTC_ARGCHK(key    != NULL);
44
45    /* is the key of the right type for the operation? */
46    if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) {
47       return CRYPT_PK_NOT_PRIVATE;
48    }
49
50    /* must be a private or public operation */
51    if (which != PK_PRIVATE && which != PK_PUBLIC) {
52       return CRYPT_PK_INVALID_TYPE;
53    }
54
55    /* init and copy into tmp */
56    if ((err = mp_init_multi(&tmp, &tmpa, &tmpb,
57 #ifdef LTC_RSA_BLINDING
58                                                &rnd, &rndi,
59 #endif /* LTC_RSA_BLINDING */
60                                                            NULL)) != CRYPT_OK)
61         { return err; }
62    if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK)
63         { goto error; }
64
65
66    /* sanity check on the input */
67    if (mp_cmp(key->N, tmp) == LTC_MP_LT) {
68       err = CRYPT_PK_INVALID_SIZE;
69       goto error;
70    }
71
72    /* are we using the private exponent and is the key optimized? */
73    if (which == PK_PRIVATE) {
74       #ifdef LTC_RSA_BLINDING
75       /* do blinding */
76       err = mp_rand(rnd, mp_get_digit_count(key->N));
77       if (err != CRYPT_OK) {
78              goto error;
79       }
80
81       /* rndi = 1/rnd mod N */
82       err = mp_invmod(rnd, key->N, rndi);
83       if (err != CRYPT_OK) {
84              goto error;
85       }
86
87       /* rnd = rnd^e */
88       err = mp_exptmod( rnd, key->e, key->N, rnd);
89       if (err != CRYPT_OK) {
90              goto error;
91       }
92
93       /* tmp = tmp*rnd mod N */
94       err = mp_mulmod( tmp, rnd, key->N, tmp);
95       if (err != CRYPT_OK) {
96              goto error;
97       }
98       #endif /* LTC_RSA_BLINDING */
99
100       has_crt_parameters = (key->p != NULL) && (mp_get_digit_count(key->p) != 0) &&
101                               (key->q != NULL) && (mp_get_digit_count(key->q) != 0) &&
102                                  (key->dP != NULL) && (mp_get_digit_count(key->dP) != 0) &&
103                                     (key->dQ != NULL) && (mp_get_digit_count(key->dQ) != 0) &&
104                                        (key->qP != NULL) && (mp_get_digit_count(key->qP) != 0);
105
106       if (!has_crt_parameters) {
107          /*
108           * In case CRT optimization parameters are not provided,
109           * the private key is directly used to exptmod it
110           */
111          if ((err = mp_exptmod(tmp, key->d, key->N, tmp)) != CRYPT_OK)                              { goto error; }
112       } else {
113          /* tmpa = tmp^dP mod p */
114          if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK)                            { goto error; }
115
116          /* tmpb = tmp^dQ mod q */
117          if ((err = mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK)                            { goto error; }
118
119          /* tmp = (tmpa - tmpb) * qInv (mod p) */
120          if ((err = mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK)                                           { goto error; }
121          if ((err = mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK)                              { goto error; }
122
123          /* tmp = tmpb + q * tmp */
124          if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK)                                          { goto error; }
125          if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK)                                            { goto error; }
126       }
127
128       #ifdef LTC_RSA_BLINDING
129       /* unblind */
130       err = mp_mulmod( tmp, rndi, key->N, tmp);
131       if (err != CRYPT_OK) {
132              goto error;
133       }
134       #endif
135
136       #ifdef LTC_RSA_CRT_HARDENING
137       if (has_crt_parameters) {
138          if ((err = mp_exptmod(tmp, key->e, key->N, tmpa)) != CRYPT_OK)                              { goto error; }
139          if ((err = mp_read_unsigned_bin(tmpb, (unsigned char *)in, (int)inlen)) != CRYPT_OK)        { goto error; }
140          if (mp_cmp(tmpa, tmpb) != LTC_MP_EQ)                                     { err = CRYPT_ERROR; goto error; }
141       }
142       #endif
143    } else {
144       /* exptmod it */
145       if ((err = mp_exptmod(tmp, key->e, key->N, tmp)) != CRYPT_OK)                                { goto error; }
146    }
147
148    /* read it back */
149    x = (unsigned long)mp_unsigned_bin_size(key->N);
150    if (x > *outlen) {
151       *outlen = x;
152       err = CRYPT_BUFFER_OVERFLOW;
153       goto error;
154    }
155
156    /* this should never happen ... */
157    if (mp_unsigned_bin_size(tmp) > mp_unsigned_bin_size(key->N)) {
158       err = CRYPT_ERROR;
159       goto error;
160    }
161    *outlen = x;
162
163    /* convert it */
164    zeromem(out, x);
165    if ((err = mp_to_unsigned_bin(tmp, out+(x-mp_unsigned_bin_size(tmp)))) != CRYPT_OK)               { goto error; }
166
167    /* clean up and return */
168    err = CRYPT_OK;
169 error:
170    mp_clear_multi(
171 #ifdef LTC_RSA_BLINDING
172                   rndi, rnd,
173 #endif /* LTC_RSA_BLINDING */
174                              tmpb, tmpa, tmp, NULL);
175    return err;
176 }
177
178 #endif
179
180 /* ref:         $Format:%D$ */
181 /* git commit:  $Format:%H$ */
182 /* commit time: $Format:%ai$ */