dd

Fork of CyaSSL by Todd Ouska

Committer:
saranieves92
Date:
Fri Feb 20 18:37:29 2015 +0000
Revision:
2:ca372ff4b2fe
Parent:
0:5045d2638c29
intento de rsa

Who changed what in which revision?

UserRevisionLine numberNew contents of line
toddouska 0:5045d2638c29 1 /* rsa.c
toddouska 0:5045d2638c29 2 *
toddouska 0:5045d2638c29 3 * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
toddouska 0:5045d2638c29 4 *
toddouska 0:5045d2638c29 5 * This file is part of CyaSSL.
toddouska 0:5045d2638c29 6 *
toddouska 0:5045d2638c29 7 * CyaSSL is free software; you can redistribute it and/or modify
toddouska 0:5045d2638c29 8 * it under the terms of the GNU General Public License as published by
toddouska 0:5045d2638c29 9 * the Free Software Foundation; either version 2 of the License, or
toddouska 0:5045d2638c29 10 * (at your option) any later version.
toddouska 0:5045d2638c29 11 *
toddouska 0:5045d2638c29 12 * CyaSSL is distributed in the hope that it will be useful,
toddouska 0:5045d2638c29 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
toddouska 0:5045d2638c29 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
toddouska 0:5045d2638c29 15 * GNU General Public License for more details.
toddouska 0:5045d2638c29 16 *
toddouska 0:5045d2638c29 17 * You should have received a copy of the GNU General Public License
toddouska 0:5045d2638c29 18 * along with this program; if not, write to the Free Software
toddouska 0:5045d2638c29 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
toddouska 0:5045d2638c29 20 */
toddouska 0:5045d2638c29 21
toddouska 0:5045d2638c29 22
toddouska 0:5045d2638c29 23
toddouska 0:5045d2638c29 24 #include "ctc_rsa.h"
toddouska 0:5045d2638c29 25 #include "random.h"
toddouska 0:5045d2638c29 26 #include "error.h"
toddouska 0:5045d2638c29 27
toddouska 0:5045d2638c29 28 #ifdef SHOW_GEN
toddouska 0:5045d2638c29 29 #include <stdio.h>
toddouska 0:5045d2638c29 30 #endif
toddouska 0:5045d2638c29 31
toddouska 0:5045d2638c29 32
toddouska 0:5045d2638c29 33 enum {
toddouska 0:5045d2638c29 34 RSA_PUBLIC_ENCRYPT = 0,
toddouska 0:5045d2638c29 35 RSA_PUBLIC_DECRYPT = 1,
toddouska 0:5045d2638c29 36 RSA_PRIVATE_ENCRYPT = 2,
toddouska 0:5045d2638c29 37 RSA_PRIVATE_DECRYPT = 3,
toddouska 0:5045d2638c29 38
toddouska 0:5045d2638c29 39 RSA_BLOCK_TYPE_1 = 1,
toddouska 0:5045d2638c29 40 RSA_BLOCK_TYPE_2 = 2,
toddouska 0:5045d2638c29 41
toddouska 0:5045d2638c29 42 RSA_MIN_SIZE = 512,
toddouska 0:5045d2638c29 43 RSA_MAX_SIZE = 4096,
toddouska 0:5045d2638c29 44
toddouska 0:5045d2638c29 45 RSA_MIN_PAD_SZ = 11 /* seperator + 0 + pad value + 8 pads */
toddouska 0:5045d2638c29 46 };
toddouska 0:5045d2638c29 47
saranieves92 2:ca372ff4b2fe 48 int MakeRsaKey(RsaKey* key, int size, long e, RNG* rng)
saranieves92 2:ca372ff4b2fe 49 {
saranieves92 2:ca372ff4b2fe 50 mp_int p, q, tmp1, tmp2, tmp3;
saranieves92 2:ca372ff4b2fe 51 int err;
toddouska 0:5045d2638c29 52
saranieves92 2:ca372ff4b2fe 53 if (key == NULL || rng == NULL)
saranieves92 2:ca372ff4b2fe 54 return -1;
saranieves92 2:ca372ff4b2fe 55
saranieves92 2:ca372ff4b2fe 56 if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE)
saranieves92 2:ca372ff4b2fe 57 return -1;
saranieves92 2:ca372ff4b2fe 58
saranieves92 2:ca372ff4b2fe 59 if (e < 3 || (e & 1) == 0)
saranieves92 2:ca372ff4b2fe 60 return -1;
saranieves92 2:ca372ff4b2fe 61
saranieves92 2:ca372ff4b2fe 62 if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY)
saranieves92 2:ca372ff4b2fe 63 return err;
saranieves92 2:ca372ff4b2fe 64
saranieves92 2:ca372ff4b2fe 65 err = mp_set_int(&tmp3, e);
saranieves92 2:ca372ff4b2fe 66
saranieves92 2:ca372ff4b2fe 67 /* make p */
saranieves92 2:ca372ff4b2fe 68 if (err == MP_OKAY) {
saranieves92 2:ca372ff4b2fe 69 do {
saranieves92 2:ca372ff4b2fe 70 err = rand_prime(&p, size/16, rng, key->heap); /* size in bytes/2 */
saranieves92 2:ca372ff4b2fe 71
saranieves92 2:ca372ff4b2fe 72 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 73 err = mp_sub_d(&p, 1, &tmp1); /* tmp1 = p-1 */
saranieves92 2:ca372ff4b2fe 74
saranieves92 2:ca372ff4b2fe 75 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 76 err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(p-1, e) */
saranieves92 2:ca372ff4b2fe 77 } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divdes p-1 */
saranieves92 2:ca372ff4b2fe 78 }
saranieves92 2:ca372ff4b2fe 79
saranieves92 2:ca372ff4b2fe 80 /* make q */
saranieves92 2:ca372ff4b2fe 81 if (err == MP_OKAY) {
saranieves92 2:ca372ff4b2fe 82 do {
saranieves92 2:ca372ff4b2fe 83 err = rand_prime(&q, size/16, rng, key->heap); /* size in bytes/2 */
saranieves92 2:ca372ff4b2fe 84
saranieves92 2:ca372ff4b2fe 85 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 86 err = mp_sub_d(&q, 1, &tmp1); /* tmp1 = q-1 */
saranieves92 2:ca372ff4b2fe 87
saranieves92 2:ca372ff4b2fe 88 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 89 err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(q-1, e) */
saranieves92 2:ca372ff4b2fe 90 } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divdes q-1 */
saranieves92 2:ca372ff4b2fe 91 }
saranieves92 2:ca372ff4b2fe 92
saranieves92 2:ca372ff4b2fe 93 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 94 err = mp_init_multi(&key->n, &key->e, &key->d, &key->p, &key->q, NULL);
saranieves92 2:ca372ff4b2fe 95
saranieves92 2:ca372ff4b2fe 96 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 97 err = mp_init_multi(&key->dP, &key->dP, &key->u, NULL, NULL, NULL);
saranieves92 2:ca372ff4b2fe 98
saranieves92 2:ca372ff4b2fe 99 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 100 err = mp_sub_d(&p, 1, &tmp2); /* tmp2 = p-1 */
saranieves92 2:ca372ff4b2fe 101
saranieves92 2:ca372ff4b2fe 102 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 103 err = mp_lcm(&tmp1, &tmp2, &tmp1); /* tmp1 = lcm(p-1, q-1),last loop */
saranieves92 2:ca372ff4b2fe 104
saranieves92 2:ca372ff4b2fe 105 /* make key */
saranieves92 2:ca372ff4b2fe 106 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 107 err = mp_set_int(&key->e, e); /* key->e = e */
saranieves92 2:ca372ff4b2fe 108
saranieves92 2:ca372ff4b2fe 109 if (err == MP_OKAY) /* key->d = 1/e mod lcm(p-1, q-1) */
saranieves92 2:ca372ff4b2fe 110 err = mp_invmod(&key->e, &tmp1, &key->d);
saranieves92 2:ca372ff4b2fe 111
saranieves92 2:ca372ff4b2fe 112 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 113 err = mp_mul(&p, &q, &key->n); /* key->n = pq */
saranieves92 2:ca372ff4b2fe 114
saranieves92 2:ca372ff4b2fe 115 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 116 err = mp_sub_d(&p, 1, &tmp1);
saranieves92 2:ca372ff4b2fe 117
saranieves92 2:ca372ff4b2fe 118 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 119 err = mp_sub_d(&q, 1, &tmp2);
saranieves92 2:ca372ff4b2fe 120
saranieves92 2:ca372ff4b2fe 121 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 122 err = mp_mod(&key->d, &tmp1, &key->dP);
saranieves92 2:ca372ff4b2fe 123
saranieves92 2:ca372ff4b2fe 124 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 125 err = mp_mod(&key->d, &tmp2, &key->dQ);
saranieves92 2:ca372ff4b2fe 126
saranieves92 2:ca372ff4b2fe 127 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 128 err = mp_invmod(&q, &p, &key->u);
saranieves92 2:ca372ff4b2fe 129
saranieves92 2:ca372ff4b2fe 130 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 131 err = mp_copy(&p, &key->p);
saranieves92 2:ca372ff4b2fe 132
saranieves92 2:ca372ff4b2fe 133 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 134 err = mp_copy(&q, &key->q);
saranieves92 2:ca372ff4b2fe 135
saranieves92 2:ca372ff4b2fe 136 if (err == MP_OKAY)
saranieves92 2:ca372ff4b2fe 137 key->type = RSA_PRIVATE;
saranieves92 2:ca372ff4b2fe 138
saranieves92 2:ca372ff4b2fe 139 mp_clear(&tmp3);
saranieves92 2:ca372ff4b2fe 140 mp_clear(&tmp2);
saranieves92 2:ca372ff4b2fe 141 mp_clear(&tmp1);
saranieves92 2:ca372ff4b2fe 142 mp_clear(&q);
saranieves92 2:ca372ff4b2fe 143 mp_clear(&p);
saranieves92 2:ca372ff4b2fe 144
saranieves92 2:ca372ff4b2fe 145 if (err != MP_OKAY) {
saranieves92 2:ca372ff4b2fe 146 FreeRsaKey(key);
saranieves92 2:ca372ff4b2fe 147 return err;
saranieves92 2:ca372ff4b2fe 148 }
saranieves92 2:ca372ff4b2fe 149
saranieves92 2:ca372ff4b2fe 150 return 0;
saranieves92 2:ca372ff4b2fe 151 }
toddouska 0:5045d2638c29 152 void InitRsaKey(RsaKey* key, void* heap)
toddouska 0:5045d2638c29 153 {
toddouska 0:5045d2638c29 154 key->type = -1; /* haven't decdied yet */
toddouska 0:5045d2638c29 155 key->heap = heap;
toddouska 0:5045d2638c29 156
toddouska 0:5045d2638c29 157 /* TomsFastMath doesn't use memory allocation */
toddouska 0:5045d2638c29 158 #ifndef USE_FAST_MATH
toddouska 0:5045d2638c29 159 key->n.dp = key->e.dp = 0; /* public alloc parts */
toddouska 0:5045d2638c29 160
toddouska 0:5045d2638c29 161 key->d.dp = key->p.dp = 0; /* private alloc parts */
toddouska 0:5045d2638c29 162 key->q.dp = key->dP.dp = 0;
toddouska 0:5045d2638c29 163 key->u.dp = key->dQ.dp = 0;
toddouska 0:5045d2638c29 164 #endif
toddouska 0:5045d2638c29 165 }
toddouska 0:5045d2638c29 166
toddouska 0:5045d2638c29 167
toddouska 0:5045d2638c29 168 void FreeRsaKey(RsaKey* key)
toddouska 0:5045d2638c29 169 {
toddouska 0:5045d2638c29 170 /* TomsFastMath doesn't use memory allocation */
toddouska 0:5045d2638c29 171 #ifndef USE_FAST_MATH
toddouska 0:5045d2638c29 172 if (key->type == RSA_PRIVATE) {
toddouska 0:5045d2638c29 173 mp_clear(&key->u);
toddouska 0:5045d2638c29 174 mp_clear(&key->dQ);
toddouska 0:5045d2638c29 175 mp_clear(&key->dP);
toddouska 0:5045d2638c29 176 mp_clear(&key->q);
toddouska 0:5045d2638c29 177 mp_clear(&key->p);
toddouska 0:5045d2638c29 178 mp_clear(&key->d);
toddouska 0:5045d2638c29 179 }
toddouska 0:5045d2638c29 180 mp_clear(&key->e);
toddouska 0:5045d2638c29 181 mp_clear(&key->n);
toddouska 0:5045d2638c29 182 #endif
toddouska 0:5045d2638c29 183 }
toddouska 0:5045d2638c29 184
toddouska 0:5045d2638c29 185 static void RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock,
toddouska 0:5045d2638c29 186 word32 pkcsBlockLen, byte padValue, RNG* rng)
toddouska 0:5045d2638c29 187 {
toddouska 0:5045d2638c29 188 if (inputLen == 0) return;
toddouska 0:5045d2638c29 189
toddouska 0:5045d2638c29 190 pkcsBlock[0] = 0x0; /* set first byte to zero and advance */
toddouska 0:5045d2638c29 191 pkcsBlock++; pkcsBlockLen--;
toddouska 0:5045d2638c29 192 pkcsBlock[0] = padValue; /* insert padValue */
toddouska 0:5045d2638c29 193
toddouska 0:5045d2638c29 194 if (padValue == RSA_BLOCK_TYPE_1)
toddouska 0:5045d2638c29 195 /* pad with 0xff bytes */
toddouska 0:5045d2638c29 196 XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2);
toddouska 0:5045d2638c29 197 else {
toddouska 0:5045d2638c29 198 /* pad with non-zero random bytes */
toddouska 0:5045d2638c29 199 word32 padLen = pkcsBlockLen - inputLen - 1, i;
toddouska 0:5045d2638c29 200 RNG_GenerateBlock(rng, &pkcsBlock[1], padLen);
toddouska 0:5045d2638c29 201
toddouska 0:5045d2638c29 202 /* remove zeros */
toddouska 0:5045d2638c29 203 for (i = 1; i < padLen; i++)
toddouska 0:5045d2638c29 204 if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01;
toddouska 0:5045d2638c29 205 }
toddouska 0:5045d2638c29 206
toddouska 0:5045d2638c29 207 pkcsBlock[pkcsBlockLen-inputLen-1] = 0; /* separator */
toddouska 0:5045d2638c29 208 XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
toddouska 0:5045d2638c29 209 }
toddouska 0:5045d2638c29 210
toddouska 0:5045d2638c29 211
toddouska 0:5045d2638c29 212 static word32 RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
toddouska 0:5045d2638c29 213 byte **output, byte padValue)
toddouska 0:5045d2638c29 214 {
toddouska 0:5045d2638c29 215 word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0,
toddouska 0:5045d2638c29 216 invalid = 0,
toddouska 0:5045d2638c29 217 i = 1,
toddouska 0:5045d2638c29 218 outputLen;
toddouska 0:5045d2638c29 219
toddouska 0:5045d2638c29 220 if (pkcsBlock[0] != 0x0) /* skip past zero */
toddouska 0:5045d2638c29 221 invalid = 1;
toddouska 0:5045d2638c29 222 pkcsBlock++; pkcsBlockLen--;
toddouska 0:5045d2638c29 223
toddouska 0:5045d2638c29 224 /* Require block type padValue */
toddouska 0:5045d2638c29 225 invalid = (pkcsBlock[0] != padValue) || invalid;
toddouska 0:5045d2638c29 226
toddouska 0:5045d2638c29 227 /* skip past the padding until we find the separator */
toddouska 0:5045d2638c29 228 while (i<pkcsBlockLen && pkcsBlock[i++]) { /* null body */
toddouska 0:5045d2638c29 229 }
toddouska 0:5045d2638c29 230 if(!(i==pkcsBlockLen || pkcsBlock[i-1]==0))
toddouska 0:5045d2638c29 231 return 0;
toddouska 0:5045d2638c29 232
toddouska 0:5045d2638c29 233 outputLen = pkcsBlockLen - i;
toddouska 0:5045d2638c29 234 invalid = (outputLen > maxOutputLen) || invalid;
toddouska 0:5045d2638c29 235
toddouska 0:5045d2638c29 236 if (invalid)
toddouska 0:5045d2638c29 237 return 0;
toddouska 0:5045d2638c29 238
toddouska 0:5045d2638c29 239 *output = (byte *)(pkcsBlock + i);
toddouska 0:5045d2638c29 240 return outputLen;
toddouska 0:5045d2638c29 241 }
toddouska 0:5045d2638c29 242
toddouska 0:5045d2638c29 243
toddouska 0:5045d2638c29 244 static int RsaFunction(const byte* in, word32 inLen, byte* out, word32* outLen,
toddouska 0:5045d2638c29 245 int type, RsaKey* key)
toddouska 0:5045d2638c29 246 {
toddouska 0:5045d2638c29 247 #define ERROR_OUT(x) { ret = x; goto done;}
toddouska 0:5045d2638c29 248
toddouska 0:5045d2638c29 249 mp_int tmp;
toddouska 0:5045d2638c29 250 int ret = 0;
toddouska 0:5045d2638c29 251 word32 keyLen, len;
toddouska 0:5045d2638c29 252
toddouska 0:5045d2638c29 253 if (mp_init(&tmp) != MP_OKAY)
toddouska 0:5045d2638c29 254 return MP_INIT_E;
toddouska 0:5045d2638c29 255
toddouska 0:5045d2638c29 256 if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY)
toddouska 0:5045d2638c29 257 ERROR_OUT(MP_READ_E);
toddouska 0:5045d2638c29 258
toddouska 0:5045d2638c29 259 if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) {
toddouska 0:5045d2638c29 260 #ifdef RSA_LOW_MEM /* half as much memory but twice as slow */
toddouska 0:5045d2638c29 261 if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY)
toddouska 0:5045d2638c29 262 ERROR_OUT(MP_EXPTMOD_E);
toddouska 0:5045d2638c29 263 #else
toddouska 0:5045d2638c29 264 #define INNER_ERROR_OUT(x) { ret = x; goto inner_done; }
toddouska 0:5045d2638c29 265
toddouska 0:5045d2638c29 266 mp_int tmpa, tmpb;
toddouska 0:5045d2638c29 267
toddouska 0:5045d2638c29 268 if (mp_init(&tmpa) != MP_OKAY)
toddouska 0:5045d2638c29 269 ERROR_OUT(MP_INIT_E);
toddouska 0:5045d2638c29 270
toddouska 0:5045d2638c29 271 if (mp_init(&tmpb) != MP_OKAY) {
toddouska 0:5045d2638c29 272 mp_clear(&tmpa);
toddouska 0:5045d2638c29 273 ERROR_OUT(MP_INIT_E);
toddouska 0:5045d2638c29 274 }
toddouska 0:5045d2638c29 275
toddouska 0:5045d2638c29 276 /* tmpa = tmp^dP mod p */
toddouska 0:5045d2638c29 277 if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY)
toddouska 0:5045d2638c29 278 INNER_ERROR_OUT(MP_EXPTMOD_E);
toddouska 0:5045d2638c29 279
toddouska 0:5045d2638c29 280 /* tmpb = tmp^dQ mod q */
toddouska 0:5045d2638c29 281 if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY)
toddouska 0:5045d2638c29 282 INNER_ERROR_OUT(MP_EXPTMOD_E);
toddouska 0:5045d2638c29 283
toddouska 0:5045d2638c29 284 /* tmp = (tmpa - tmpb) * qInv (mod p) */
toddouska 0:5045d2638c29 285 if (mp_sub(&tmpa, &tmpb, &tmp) != MP_OKAY)
toddouska 0:5045d2638c29 286 INNER_ERROR_OUT(MP_SUB_E);
toddouska 0:5045d2638c29 287
toddouska 0:5045d2638c29 288 if (mp_mulmod(&tmp, &key->u, &key->p, &tmp) != MP_OKAY)
toddouska 0:5045d2638c29 289 INNER_ERROR_OUT(MP_MULMOD_E);
toddouska 0:5045d2638c29 290
toddouska 0:5045d2638c29 291 /* tmp = tmpb + q * tmp */
toddouska 0:5045d2638c29 292 if (mp_mul(&tmp, &key->q, &tmp) != MP_OKAY)
toddouska 0:5045d2638c29 293 INNER_ERROR_OUT(MP_MUL_E);
toddouska 0:5045d2638c29 294
toddouska 0:5045d2638c29 295 if (mp_add(&tmp, &tmpb, &tmp) != MP_OKAY)
toddouska 0:5045d2638c29 296 INNER_ERROR_OUT(MP_ADD_E);
toddouska 0:5045d2638c29 297
toddouska 0:5045d2638c29 298 inner_done:
toddouska 0:5045d2638c29 299 mp_clear(&tmpa);
toddouska 0:5045d2638c29 300 mp_clear(&tmpb);
toddouska 0:5045d2638c29 301
toddouska 0:5045d2638c29 302 if (ret != 0) return ret;
toddouska 0:5045d2638c29 303
toddouska 0:5045d2638c29 304 #endif /* RSA_LOW_MEM */
toddouska 0:5045d2638c29 305 }
toddouska 0:5045d2638c29 306 else if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) {
toddouska 0:5045d2638c29 307 if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY)
toddouska 0:5045d2638c29 308 ERROR_OUT(MP_EXPTMOD_E);
toddouska 0:5045d2638c29 309 }
toddouska 0:5045d2638c29 310 else
toddouska 0:5045d2638c29 311 ERROR_OUT(RSA_WRONG_TYPE_E);
toddouska 0:5045d2638c29 312
toddouska 0:5045d2638c29 313 keyLen = mp_unsigned_bin_size(&key->n);
toddouska 0:5045d2638c29 314 if (keyLen > *outLen)
toddouska 0:5045d2638c29 315 ERROR_OUT(RSA_BUFFER_E);
toddouska 0:5045d2638c29 316
toddouska 0:5045d2638c29 317 len = mp_unsigned_bin_size(&tmp);
toddouska 0:5045d2638c29 318
toddouska 0:5045d2638c29 319 /* pad front w/ zeros to match key length */
toddouska 0:5045d2638c29 320 while (len < keyLen) {
toddouska 0:5045d2638c29 321 *out++ = 0x00;
toddouska 0:5045d2638c29 322 len++;
toddouska 0:5045d2638c29 323 }
toddouska 0:5045d2638c29 324
toddouska 0:5045d2638c29 325 *outLen = keyLen;
toddouska 0:5045d2638c29 326
toddouska 0:5045d2638c29 327 /* convert */
toddouska 0:5045d2638c29 328 if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY)
toddouska 0:5045d2638c29 329 ERROR_OUT(MP_TO_E);
toddouska 0:5045d2638c29 330
toddouska 0:5045d2638c29 331 done:
toddouska 0:5045d2638c29 332 mp_clear(&tmp);
toddouska 0:5045d2638c29 333 return ret;
toddouska 0:5045d2638c29 334 }
toddouska 0:5045d2638c29 335
toddouska 0:5045d2638c29 336
toddouska 0:5045d2638c29 337
toddouska 0:5045d2638c29 338 int RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
toddouska 0:5045d2638c29 339 RsaKey* key, RNG* rng)
toddouska 0:5045d2638c29 340 {
toddouska 0:5045d2638c29 341 int sz = mp_unsigned_bin_size(&key->n), ret;
toddouska 0:5045d2638c29 342
toddouska 0:5045d2638c29 343 if (sz > (int)outLen)
toddouska 0:5045d2638c29 344 return RSA_BUFFER_E;
toddouska 0:5045d2638c29 345
toddouska 0:5045d2638c29 346 if (inLen > (word32)(sz - RSA_MIN_PAD_SZ))
toddouska 0:5045d2638c29 347 return RSA_BUFFER_E;
toddouska 0:5045d2638c29 348
toddouska 0:5045d2638c29 349 RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_2, rng);
toddouska 0:5045d2638c29 350
toddouska 0:5045d2638c29 351 if ((ret = RsaFunction(out, sz, out, &outLen, RSA_PUBLIC_ENCRYPT, key)) < 0)
toddouska 0:5045d2638c29 352 sz = ret;
toddouska 0:5045d2638c29 353
toddouska 0:5045d2638c29 354 return sz;
toddouska 0:5045d2638c29 355 }
toddouska 0:5045d2638c29 356
toddouska 0:5045d2638c29 357
toddouska 0:5045d2638c29 358 int RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key)
toddouska 0:5045d2638c29 359 {
toddouska 0:5045d2638c29 360 int plainLen, ret;
toddouska 0:5045d2638c29 361
toddouska 0:5045d2638c29 362 if ((ret = RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key))
toddouska 0:5045d2638c29 363 < 0) {
toddouska 0:5045d2638c29 364 return ret;
toddouska 0:5045d2638c29 365 }
toddouska 0:5045d2638c29 366
toddouska 0:5045d2638c29 367 plainLen = RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_2);
toddouska 0:5045d2638c29 368
toddouska 0:5045d2638c29 369 return plainLen;
toddouska 0:5045d2638c29 370 }
toddouska 0:5045d2638c29 371
toddouska 0:5045d2638c29 372 int RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
toddouska 0:5045d2638c29 373 RsaKey* key)
toddouska 0:5045d2638c29 374 {
toddouska 0:5045d2638c29 375 int plainLen, ret;
toddouska 0:5045d2638c29 376 byte* tmp;
toddouska 0:5045d2638c29 377 byte* pad = 0;
toddouska 0:5045d2638c29 378
toddouska 0:5045d2638c29 379 if ( !(tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA)) )
toddouska 0:5045d2638c29 380 return MEMORY_E;
toddouska 0:5045d2638c29 381
toddouska 0:5045d2638c29 382 XMEMCPY(tmp, in, inLen);
toddouska 0:5045d2638c29 383
toddouska 0:5045d2638c29 384 if ((ret = plainLen = RsaPrivateDecryptInline(tmp, inLen, &pad, key))
toddouska 0:5045d2638c29 385 < 0) {
toddouska 0:5045d2638c29 386 XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
toddouska 0:5045d2638c29 387 return ret;
toddouska 0:5045d2638c29 388 }
toddouska 0:5045d2638c29 389 XMEMCPY(out, pad, plainLen);
toddouska 0:5045d2638c29 390 XMEMSET(tmp, 0x00, inLen);
toddouska 0:5045d2638c29 391
toddouska 0:5045d2638c29 392 XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
toddouska 0:5045d2638c29 393 return plainLen;
toddouska 0:5045d2638c29 394 }
toddouska 0:5045d2638c29 395
toddouska 0:5045d2638c29 396
toddouska 0:5045d2638c29 397 /* for Rsa Verify */
toddouska 0:5045d2638c29 398 int RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
toddouska 0:5045d2638c29 399 {
toddouska 0:5045d2638c29 400 int plainLen, ret;
toddouska 0:5045d2638c29 401
toddouska 0:5045d2638c29 402 if ((ret = RsaFunction(in, inLen, in, &inLen, RSA_PUBLIC_DECRYPT, key))
toddouska 0:5045d2638c29 403 < 0) {
toddouska 0:5045d2638c29 404 return ret;
toddouska 0:5045d2638c29 405 }
toddouska 0:5045d2638c29 406
toddouska 0:5045d2638c29 407 plainLen = RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1);
toddouska 0:5045d2638c29 408
toddouska 0:5045d2638c29 409 return plainLen;
toddouska 0:5045d2638c29 410 }
toddouska 0:5045d2638c29 411
toddouska 0:5045d2638c29 412 int RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen,
toddouska 0:5045d2638c29 413 RsaKey* key)
toddouska 0:5045d2638c29 414 {
toddouska 0:5045d2638c29 415 int plainLen, ret;
toddouska 0:5045d2638c29 416 byte* tmp;
toddouska 0:5045d2638c29 417 byte* pad = 0;
toddouska 0:5045d2638c29 418
toddouska 0:5045d2638c29 419 if ( !(tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA)) )
toddouska 0:5045d2638c29 420 return MEMORY_E;
toddouska 0:5045d2638c29 421
toddouska 0:5045d2638c29 422 XMEMCPY(tmp, in, inLen);
toddouska 0:5045d2638c29 423
toddouska 0:5045d2638c29 424 if ((ret = plainLen = RsaSSL_VerifyInline(tmp, inLen, &pad, key))
toddouska 0:5045d2638c29 425 < 0) {
toddouska 0:5045d2638c29 426 XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
toddouska 0:5045d2638c29 427 return ret;
toddouska 0:5045d2638c29 428 }
toddouska 0:5045d2638c29 429
toddouska 0:5045d2638c29 430 XMEMCPY(out, pad, plainLen);
toddouska 0:5045d2638c29 431 XMEMSET(tmp, 0x00, inLen);
toddouska 0:5045d2638c29 432
toddouska 0:5045d2638c29 433 XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
toddouska 0:5045d2638c29 434 return plainLen;
toddouska 0:5045d2638c29 435 }
toddouska 0:5045d2638c29 436
toddouska 0:5045d2638c29 437
toddouska 0:5045d2638c29 438 /* for Rsa Sign */
toddouska 0:5045d2638c29 439 int RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen,
toddouska 0:5045d2638c29 440 RsaKey* key, RNG* rng)
toddouska 0:5045d2638c29 441 {
toddouska 0:5045d2638c29 442 int sz = mp_unsigned_bin_size(&key->n), ret;
toddouska 0:5045d2638c29 443
toddouska 0:5045d2638c29 444 if (sz > (int)outLen)
toddouska 0:5045d2638c29 445 return RSA_BUFFER_E;
toddouska 0:5045d2638c29 446
toddouska 0:5045d2638c29 447 if (inLen > (word32)(sz - RSA_MIN_PAD_SZ))
toddouska 0:5045d2638c29 448 return RSA_BUFFER_E;
toddouska 0:5045d2638c29 449
toddouska 0:5045d2638c29 450 RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_1, rng);
toddouska 0:5045d2638c29 451
toddouska 0:5045d2638c29 452 if ((ret = RsaFunction(out, sz, out, &outLen, RSA_PRIVATE_ENCRYPT,key)) < 0)
toddouska 0:5045d2638c29 453 sz = ret;
toddouska 0:5045d2638c29 454
toddouska 0:5045d2638c29 455 return sz;
toddouska 0:5045d2638c29 456 }
toddouska 0:5045d2638c29 457
toddouska 0:5045d2638c29 458
toddouska 0:5045d2638c29 459 int RsaEncryptSize(RsaKey* key)
toddouska 0:5045d2638c29 460 {
toddouska 0:5045d2638c29 461 return mp_unsigned_bin_size(&key->n);
toddouska 0:5045d2638c29 462 }
toddouska 0:5045d2638c29 463
toddouska 0:5045d2638c29 464
toddouska 0:5045d2638c29 465 #ifdef CYASSL_KEY_GEN
toddouska 0:5045d2638c29 466
toddouska 0:5045d2638c29 467 static const int USE_BBS = 1;
toddouska 0:5045d2638c29 468
toddouska 0:5045d2638c29 469 static int rand_prime(mp_int* N, int len, RNG* rng, void* heap)
toddouska 0:5045d2638c29 470 {
toddouska 0:5045d2638c29 471 int err, res, type;
toddouska 0:5045d2638c29 472 byte* buf;
toddouska 0:5045d2638c29 473
toddouska 0:5045d2638c29 474 if (N == NULL || rng == NULL)
toddouska 0:5045d2638c29 475 return -1;
toddouska 0:5045d2638c29 476
toddouska 0:5045d2638c29 477 /* get type */
toddouska 0:5045d2638c29 478 if (len < 0) {
toddouska 0:5045d2638c29 479 type = USE_BBS;
toddouska 0:5045d2638c29 480 len = -len;
toddouska 0:5045d2638c29 481 } else {
toddouska 0:5045d2638c29 482 type = 0;
toddouska 0:5045d2638c29 483 }
toddouska 0:5045d2638c29 484
toddouska 0:5045d2638c29 485 /* allow sizes between 2 and 512 bytes for a prime size */
toddouska 0:5045d2638c29 486 if (len < 2 || len > 512) {
toddouska 0:5045d2638c29 487 return -1;
toddouska 0:5045d2638c29 488 }
toddouska 0:5045d2638c29 489
toddouska 0:5045d2638c29 490 /* allocate buffer to work with */
toddouska 0:5045d2638c29 491 buf = XCALLOC(1, len, heap);
toddouska 0:5045d2638c29 492 if (buf == NULL) {
toddouska 0:5045d2638c29 493 return -1;
toddouska 0:5045d2638c29 494 }
toddouska 0:5045d2638c29 495
toddouska 0:5045d2638c29 496 do {
toddouska 0:5045d2638c29 497 #ifdef SHOW_GEN
toddouska 0:5045d2638c29 498 printf(".");
toddouska 0:5045d2638c29 499 fflush(stdout);
toddouska 0:5045d2638c29 500 #endif
toddouska 0:5045d2638c29 501 /* generate value */
toddouska 0:5045d2638c29 502 RNG_GenerateBlock(rng, buf, len);
toddouska 0:5045d2638c29 503
toddouska 0:5045d2638c29 504 /* munge bits */
toddouska 0:5045d2638c29 505 buf[0] |= 0x80 | 0x40;
toddouska 0:5045d2638c29 506 buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
toddouska 0:5045d2638c29 507
toddouska 0:5045d2638c29 508 /* load value */
toddouska 0:5045d2638c29 509 if ((err = mp_read_unsigned_bin(N, buf, len)) != MP_OKAY) {
toddouska 0:5045d2638c29 510 XFREE(buf, heap, DYNAMIC_TYPE_RSA);
toddouska 0:5045d2638c29 511 return err;
toddouska 0:5045d2638c29 512 }
toddouska 0:5045d2638c29 513
toddouska 0:5045d2638c29 514 /* test */
toddouska 0:5045d2638c29 515 if ((err = mp_prime_is_prime(N, 8, &res)) != MP_OKAY) {
toddouska 0:5045d2638c29 516 XFREE(buf, heap, DYNAMIC_TYPE_RSA);
toddouska 0:5045d2638c29 517 return err;
toddouska 0:5045d2638c29 518 }
toddouska 0:5045d2638c29 519 } while (res == MP_NO);
toddouska 0:5045d2638c29 520
toddouska 0:5045d2638c29 521 #ifdef LTC_CLEAN_STACK
toddouska 0:5045d2638c29 522 XMEMSET(buf, 0, len);
toddouska 0:5045d2638c29 523 #endif
toddouska 0:5045d2638c29 524
toddouska 0:5045d2638c29 525 XFREE(buf, heap, DYNAMIC_TYPE_RSA);
toddouska 0:5045d2638c29 526 return 0;
toddouska 0:5045d2638c29 527 }
toddouska 0:5045d2638c29 528
toddouska 0:5045d2638c29 529
toddouska 0:5045d2638c29 530 /* Make an RSA key for size bits, with e specified, 65537 is a good e */
toddouska 0:5045d2638c29 531 int MakeRsaKey(RsaKey* key, int size, long e, RNG* rng)
toddouska 0:5045d2638c29 532 {
toddouska 0:5045d2638c29 533 mp_int p, q, tmp1, tmp2, tmp3;
toddouska 0:5045d2638c29 534 int err;
toddouska 0:5045d2638c29 535
toddouska 0:5045d2638c29 536 if (key == NULL || rng == NULL)
toddouska 0:5045d2638c29 537 return -1;
toddouska 0:5045d2638c29 538
toddouska 0:5045d2638c29 539 if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE)
toddouska 0:5045d2638c29 540 return -1;
toddouska 0:5045d2638c29 541
toddouska 0:5045d2638c29 542 if (e < 3 || (e & 1) == 0)
toddouska 0:5045d2638c29 543 return -1;
toddouska 0:5045d2638c29 544
toddouska 0:5045d2638c29 545 if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY)
toddouska 0:5045d2638c29 546 return err;
toddouska 0:5045d2638c29 547
toddouska 0:5045d2638c29 548 err = mp_set_int(&tmp3, e);
toddouska 0:5045d2638c29 549
toddouska 0:5045d2638c29 550 /* make p */
toddouska 0:5045d2638c29 551 if (err == MP_OKAY) {
toddouska 0:5045d2638c29 552 do {
toddouska 0:5045d2638c29 553 err = rand_prime(&p, size/16, rng, key->heap); /* size in bytes/2 */
toddouska 0:5045d2638c29 554
toddouska 0:5045d2638c29 555 if (err == MP_OKAY)
toddouska 0:5045d2638c29 556 err = mp_sub_d(&p, 1, &tmp1); /* tmp1 = p-1 */
toddouska 0:5045d2638c29 557
toddouska 0:5045d2638c29 558 if (err == MP_OKAY)
toddouska 0:5045d2638c29 559 err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(p-1, e) */
toddouska 0:5045d2638c29 560 } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divdes p-1 */
toddouska 0:5045d2638c29 561 }
toddouska 0:5045d2638c29 562
toddouska 0:5045d2638c29 563 /* make q */
toddouska 0:5045d2638c29 564 if (err == MP_OKAY) {
toddouska 0:5045d2638c29 565 do {
toddouska 0:5045d2638c29 566 err = rand_prime(&q, size/16, rng, key->heap); /* size in bytes/2 */
toddouska 0:5045d2638c29 567
toddouska 0:5045d2638c29 568 if (err == MP_OKAY)
toddouska 0:5045d2638c29 569 err = mp_sub_d(&q, 1, &tmp1); /* tmp1 = q-1 */
toddouska 0:5045d2638c29 570
toddouska 0:5045d2638c29 571 if (err == MP_OKAY)
toddouska 0:5045d2638c29 572 err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(q-1, e) */
toddouska 0:5045d2638c29 573 } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divdes q-1 */
toddouska 0:5045d2638c29 574 }
toddouska 0:5045d2638c29 575
toddouska 0:5045d2638c29 576 if (err == MP_OKAY)
toddouska 0:5045d2638c29 577 err = mp_init_multi(&key->n, &key->e, &key->d, &key->p, &key->q, NULL);
toddouska 0:5045d2638c29 578
toddouska 0:5045d2638c29 579 if (err == MP_OKAY)
toddouska 0:5045d2638c29 580 err = mp_init_multi(&key->dP, &key->dP, &key->u, NULL, NULL, NULL);
toddouska 0:5045d2638c29 581
toddouska 0:5045d2638c29 582 if (err == MP_OKAY)
toddouska 0:5045d2638c29 583 err = mp_sub_d(&p, 1, &tmp2); /* tmp2 = p-1 */
toddouska 0:5045d2638c29 584
toddouska 0:5045d2638c29 585 if (err == MP_OKAY)
toddouska 0:5045d2638c29 586 err = mp_lcm(&tmp1, &tmp2, &tmp1); /* tmp1 = lcm(p-1, q-1),last loop */
toddouska 0:5045d2638c29 587
toddouska 0:5045d2638c29 588 /* make key */
toddouska 0:5045d2638c29 589 if (err == MP_OKAY)
toddouska 0:5045d2638c29 590 err = mp_set_int(&key->e, e); /* key->e = e */
toddouska 0:5045d2638c29 591
toddouska 0:5045d2638c29 592 if (err == MP_OKAY) /* key->d = 1/e mod lcm(p-1, q-1) */
toddouska 0:5045d2638c29 593 err = mp_invmod(&key->e, &tmp1, &key->d);
toddouska 0:5045d2638c29 594
toddouska 0:5045d2638c29 595 if (err == MP_OKAY)
toddouska 0:5045d2638c29 596 err = mp_mul(&p, &q, &key->n); /* key->n = pq */
toddouska 0:5045d2638c29 597
toddouska 0:5045d2638c29 598 if (err == MP_OKAY)
toddouska 0:5045d2638c29 599 err = mp_sub_d(&p, 1, &tmp1);
toddouska 0:5045d2638c29 600
toddouska 0:5045d2638c29 601 if (err == MP_OKAY)
toddouska 0:5045d2638c29 602 err = mp_sub_d(&q, 1, &tmp2);
toddouska 0:5045d2638c29 603
toddouska 0:5045d2638c29 604 if (err == MP_OKAY)
toddouska 0:5045d2638c29 605 err = mp_mod(&key->d, &tmp1, &key->dP);
toddouska 0:5045d2638c29 606
toddouska 0:5045d2638c29 607 if (err == MP_OKAY)
toddouska 0:5045d2638c29 608 err = mp_mod(&key->d, &tmp2, &key->dQ);
toddouska 0:5045d2638c29 609
toddouska 0:5045d2638c29 610 if (err == MP_OKAY)
toddouska 0:5045d2638c29 611 err = mp_invmod(&q, &p, &key->u);
toddouska 0:5045d2638c29 612
toddouska 0:5045d2638c29 613 if (err == MP_OKAY)
toddouska 0:5045d2638c29 614 err = mp_copy(&p, &key->p);
toddouska 0:5045d2638c29 615
toddouska 0:5045d2638c29 616 if (err == MP_OKAY)
toddouska 0:5045d2638c29 617 err = mp_copy(&q, &key->q);
toddouska 0:5045d2638c29 618
toddouska 0:5045d2638c29 619 if (err == MP_OKAY)
toddouska 0:5045d2638c29 620 key->type = RSA_PRIVATE;
toddouska 0:5045d2638c29 621
toddouska 0:5045d2638c29 622 mp_clear(&tmp3);
toddouska 0:5045d2638c29 623 mp_clear(&tmp2);
toddouska 0:5045d2638c29 624 mp_clear(&tmp1);
toddouska 0:5045d2638c29 625 mp_clear(&q);
toddouska 0:5045d2638c29 626 mp_clear(&p);
toddouska 0:5045d2638c29 627
toddouska 0:5045d2638c29 628 if (err != MP_OKAY) {
toddouska 0:5045d2638c29 629 FreeRsaKey(key);
toddouska 0:5045d2638c29 630 return err;
toddouska 0:5045d2638c29 631 }
toddouska 0:5045d2638c29 632
toddouska 0:5045d2638c29 633 return 0;
toddouska 0:5045d2638c29 634 }
toddouska 0:5045d2638c29 635
toddouska 0:5045d2638c29 636
toddouska 0:5045d2638c29 637 #endif /* CYASLS_KEY_GEN */
toddouska 0:5045d2638c29 638