Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/tomcrypt/src/pk/rsa/rsa_exptmod.c
4396 views
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