CyaSSL is an SSL library for devices like mbed.

Dependents:   cyassl-client Sync

Committer:
toddouska
Date:
Sat Feb 05 01:09:17 2011 +0000
Revision:
0:5045d2638c29
Beta Version

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
toddouska 0:5045d2638c29 48
toddouska 0:5045d2638c29 49 void InitRsaKey(RsaKey* key, void* heap)
toddouska 0:5045d2638c29 50 {
toddouska 0:5045d2638c29 51 key->type = -1; /* haven't decdied yet */
toddouska 0:5045d2638c29 52 key->heap = heap;
toddouska 0:5045d2638c29 53
toddouska 0:5045d2638c29 54 /* TomsFastMath doesn't use memory allocation */
toddouska 0:5045d2638c29 55 #ifndef USE_FAST_MATH
toddouska 0:5045d2638c29 56 key->n.dp = key->e.dp = 0; /* public alloc parts */
toddouska 0:5045d2638c29 57
toddouska 0:5045d2638c29 58 key->d.dp = key->p.dp = 0; /* private alloc parts */
toddouska 0:5045d2638c29 59 key->q.dp = key->dP.dp = 0;
toddouska 0:5045d2638c29 60 key->u.dp = key->dQ.dp = 0;
toddouska 0:5045d2638c29 61 #endif
toddouska 0:5045d2638c29 62 }
toddouska 0:5045d2638c29 63
toddouska 0:5045d2638c29 64
toddouska 0:5045d2638c29 65 void FreeRsaKey(RsaKey* key)
toddouska 0:5045d2638c29 66 {
toddouska 0:5045d2638c29 67 /* TomsFastMath doesn't use memory allocation */
toddouska 0:5045d2638c29 68 #ifndef USE_FAST_MATH
toddouska 0:5045d2638c29 69 if (key->type == RSA_PRIVATE) {
toddouska 0:5045d2638c29 70 mp_clear(&key->u);
toddouska 0:5045d2638c29 71 mp_clear(&key->dQ);
toddouska 0:5045d2638c29 72 mp_clear(&key->dP);
toddouska 0:5045d2638c29 73 mp_clear(&key->q);
toddouska 0:5045d2638c29 74 mp_clear(&key->p);
toddouska 0:5045d2638c29 75 mp_clear(&key->d);
toddouska 0:5045d2638c29 76 }
toddouska 0:5045d2638c29 77 mp_clear(&key->e);
toddouska 0:5045d2638c29 78 mp_clear(&key->n);
toddouska 0:5045d2638c29 79 #endif
toddouska 0:5045d2638c29 80 }
toddouska 0:5045d2638c29 81
toddouska 0:5045d2638c29 82 static void RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock,
toddouska 0:5045d2638c29 83 word32 pkcsBlockLen, byte padValue, RNG* rng)
toddouska 0:5045d2638c29 84 {
toddouska 0:5045d2638c29 85 if (inputLen == 0) return;
toddouska 0:5045d2638c29 86
toddouska 0:5045d2638c29 87 pkcsBlock[0] = 0x0; /* set first byte to zero and advance */
toddouska 0:5045d2638c29 88 pkcsBlock++; pkcsBlockLen--;
toddouska 0:5045d2638c29 89 pkcsBlock[0] = padValue; /* insert padValue */
toddouska 0:5045d2638c29 90
toddouska 0:5045d2638c29 91 if (padValue == RSA_BLOCK_TYPE_1)
toddouska 0:5045d2638c29 92 /* pad with 0xff bytes */
toddouska 0:5045d2638c29 93 XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2);
toddouska 0:5045d2638c29 94 else {
toddouska 0:5045d2638c29 95 /* pad with non-zero random bytes */
toddouska 0:5045d2638c29 96 word32 padLen = pkcsBlockLen - inputLen - 1, i;
toddouska 0:5045d2638c29 97 RNG_GenerateBlock(rng, &pkcsBlock[1], padLen);
toddouska 0:5045d2638c29 98
toddouska 0:5045d2638c29 99 /* remove zeros */
toddouska 0:5045d2638c29 100 for (i = 1; i < padLen; i++)
toddouska 0:5045d2638c29 101 if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01;
toddouska 0:5045d2638c29 102 }
toddouska 0:5045d2638c29 103
toddouska 0:5045d2638c29 104 pkcsBlock[pkcsBlockLen-inputLen-1] = 0; /* separator */
toddouska 0:5045d2638c29 105 XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
toddouska 0:5045d2638c29 106 }
toddouska 0:5045d2638c29 107
toddouska 0:5045d2638c29 108
toddouska 0:5045d2638c29 109 static word32 RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
toddouska 0:5045d2638c29 110 byte **output, byte padValue)
toddouska 0:5045d2638c29 111 {
toddouska 0:5045d2638c29 112 word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0,
toddouska 0:5045d2638c29 113 invalid = 0,
toddouska 0:5045d2638c29 114 i = 1,
toddouska 0:5045d2638c29 115 outputLen;
toddouska 0:5045d2638c29 116
toddouska 0:5045d2638c29 117 if (pkcsBlock[0] != 0x0) /* skip past zero */
toddouska 0:5045d2638c29 118 invalid = 1;
toddouska 0:5045d2638c29 119 pkcsBlock++; pkcsBlockLen--;
toddouska 0:5045d2638c29 120
toddouska 0:5045d2638c29 121 /* Require block type padValue */
toddouska 0:5045d2638c29 122 invalid = (pkcsBlock[0] != padValue) || invalid;
toddouska 0:5045d2638c29 123
toddouska 0:5045d2638c29 124 /* skip past the padding until we find the separator */
toddouska 0:5045d2638c29 125 while (i<pkcsBlockLen && pkcsBlock[i++]) { /* null body */
toddouska 0:5045d2638c29 126 }
toddouska 0:5045d2638c29 127 if(!(i==pkcsBlockLen || pkcsBlock[i-1]==0))
toddouska 0:5045d2638c29 128 return 0;
toddouska 0:5045d2638c29 129
toddouska 0:5045d2638c29 130 outputLen = pkcsBlockLen - i;
toddouska 0:5045d2638c29 131 invalid = (outputLen > maxOutputLen) || invalid;
toddouska 0:5045d2638c29 132
toddouska 0:5045d2638c29 133 if (invalid)
toddouska 0:5045d2638c29 134 return 0;
toddouska 0:5045d2638c29 135
toddouska 0:5045d2638c29 136 *output = (byte *)(pkcsBlock + i);
toddouska 0:5045d2638c29 137 return outputLen;
toddouska 0:5045d2638c29 138 }
toddouska 0:5045d2638c29 139
toddouska 0:5045d2638c29 140
toddouska 0:5045d2638c29 141 static int RsaFunction(const byte* in, word32 inLen, byte* out, word32* outLen,
toddouska 0:5045d2638c29 142 int type, RsaKey* key)
toddouska 0:5045d2638c29 143 {
toddouska 0:5045d2638c29 144 #define ERROR_OUT(x) { ret = x; goto done;}
toddouska 0:5045d2638c29 145
toddouska 0:5045d2638c29 146 mp_int tmp;
toddouska 0:5045d2638c29 147 int ret = 0;
toddouska 0:5045d2638c29 148 word32 keyLen, len;
toddouska 0:5045d2638c29 149
toddouska 0:5045d2638c29 150 if (mp_init(&tmp) != MP_OKAY)
toddouska 0:5045d2638c29 151 return MP_INIT_E;
toddouska 0:5045d2638c29 152
toddouska 0:5045d2638c29 153 if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY)
toddouska 0:5045d2638c29 154 ERROR_OUT(MP_READ_E);
toddouska 0:5045d2638c29 155
toddouska 0:5045d2638c29 156 if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) {
toddouska 0:5045d2638c29 157 #ifdef RSA_LOW_MEM /* half as much memory but twice as slow */
toddouska 0:5045d2638c29 158 if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY)
toddouska 0:5045d2638c29 159 ERROR_OUT(MP_EXPTMOD_E);
toddouska 0:5045d2638c29 160 #else
toddouska 0:5045d2638c29 161 #define INNER_ERROR_OUT(x) { ret = x; goto inner_done; }
toddouska 0:5045d2638c29 162
toddouska 0:5045d2638c29 163 mp_int tmpa, tmpb;
toddouska 0:5045d2638c29 164
toddouska 0:5045d2638c29 165 if (mp_init(&tmpa) != MP_OKAY)
toddouska 0:5045d2638c29 166 ERROR_OUT(MP_INIT_E);
toddouska 0:5045d2638c29 167
toddouska 0:5045d2638c29 168 if (mp_init(&tmpb) != MP_OKAY) {
toddouska 0:5045d2638c29 169 mp_clear(&tmpa);
toddouska 0:5045d2638c29 170 ERROR_OUT(MP_INIT_E);
toddouska 0:5045d2638c29 171 }
toddouska 0:5045d2638c29 172
toddouska 0:5045d2638c29 173 /* tmpa = tmp^dP mod p */
toddouska 0:5045d2638c29 174 if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY)
toddouska 0:5045d2638c29 175 INNER_ERROR_OUT(MP_EXPTMOD_E);
toddouska 0:5045d2638c29 176
toddouska 0:5045d2638c29 177 /* tmpb = tmp^dQ mod q */
toddouska 0:5045d2638c29 178 if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY)
toddouska 0:5045d2638c29 179 INNER_ERROR_OUT(MP_EXPTMOD_E);
toddouska 0:5045d2638c29 180
toddouska 0:5045d2638c29 181 /* tmp = (tmpa - tmpb) * qInv (mod p) */
toddouska 0:5045d2638c29 182 if (mp_sub(&tmpa, &tmpb, &tmp) != MP_OKAY)
toddouska 0:5045d2638c29 183 INNER_ERROR_OUT(MP_SUB_E);
toddouska 0:5045d2638c29 184
toddouska 0:5045d2638c29 185 if (mp_mulmod(&tmp, &key->u, &key->p, &tmp) != MP_OKAY)
toddouska 0:5045d2638c29 186 INNER_ERROR_OUT(MP_MULMOD_E);
toddouska 0:5045d2638c29 187
toddouska 0:5045d2638c29 188 /* tmp = tmpb + q * tmp */
toddouska 0:5045d2638c29 189 if (mp_mul(&tmp, &key->q, &tmp) != MP_OKAY)
toddouska 0:5045d2638c29 190 INNER_ERROR_OUT(MP_MUL_E);
toddouska 0:5045d2638c29 191
toddouska 0:5045d2638c29 192 if (mp_add(&tmp, &tmpb, &tmp) != MP_OKAY)
toddouska 0:5045d2638c29 193 INNER_ERROR_OUT(MP_ADD_E);
toddouska 0:5045d2638c29 194
toddouska 0:5045d2638c29 195 inner_done:
toddouska 0:5045d2638c29 196 mp_clear(&tmpa);
toddouska 0:5045d2638c29 197 mp_clear(&tmpb);
toddouska 0:5045d2638c29 198
toddouska 0:5045d2638c29 199 if (ret != 0) return ret;
toddouska 0:5045d2638c29 200
toddouska 0:5045d2638c29 201 #endif /* RSA_LOW_MEM */
toddouska 0:5045d2638c29 202 }
toddouska 0:5045d2638c29 203 else if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) {
toddouska 0:5045d2638c29 204 if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY)
toddouska 0:5045d2638c29 205 ERROR_OUT(MP_EXPTMOD_E);
toddouska 0:5045d2638c29 206 }
toddouska 0:5045d2638c29 207 else
toddouska 0:5045d2638c29 208 ERROR_OUT(RSA_WRONG_TYPE_E);
toddouska 0:5045d2638c29 209
toddouska 0:5045d2638c29 210 keyLen = mp_unsigned_bin_size(&key->n);
toddouska 0:5045d2638c29 211 if (keyLen > *outLen)
toddouska 0:5045d2638c29 212 ERROR_OUT(RSA_BUFFER_E);
toddouska 0:5045d2638c29 213
toddouska 0:5045d2638c29 214 len = mp_unsigned_bin_size(&tmp);
toddouska 0:5045d2638c29 215
toddouska 0:5045d2638c29 216 /* pad front w/ zeros to match key length */
toddouska 0:5045d2638c29 217 while (len < keyLen) {
toddouska 0:5045d2638c29 218 *out++ = 0x00;
toddouska 0:5045d2638c29 219 len++;
toddouska 0:5045d2638c29 220 }
toddouska 0:5045d2638c29 221
toddouska 0:5045d2638c29 222 *outLen = keyLen;
toddouska 0:5045d2638c29 223
toddouska 0:5045d2638c29 224 /* convert */
toddouska 0:5045d2638c29 225 if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY)
toddouska 0:5045d2638c29 226 ERROR_OUT(MP_TO_E);
toddouska 0:5045d2638c29 227
toddouska 0:5045d2638c29 228 done:
toddouska 0:5045d2638c29 229 mp_clear(&tmp);
toddouska 0:5045d2638c29 230 return ret;
toddouska 0:5045d2638c29 231 }
toddouska 0:5045d2638c29 232
toddouska 0:5045d2638c29 233
toddouska 0:5045d2638c29 234
toddouska 0:5045d2638c29 235 int RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
toddouska 0:5045d2638c29 236 RsaKey* key, RNG* rng)
toddouska 0:5045d2638c29 237 {
toddouska 0:5045d2638c29 238 int sz = mp_unsigned_bin_size(&key->n), ret;
toddouska 0:5045d2638c29 239
toddouska 0:5045d2638c29 240 if (sz > (int)outLen)
toddouska 0:5045d2638c29 241 return RSA_BUFFER_E;
toddouska 0:5045d2638c29 242
toddouska 0:5045d2638c29 243 if (inLen > (word32)(sz - RSA_MIN_PAD_SZ))
toddouska 0:5045d2638c29 244 return RSA_BUFFER_E;
toddouska 0:5045d2638c29 245
toddouska 0:5045d2638c29 246 RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_2, rng);
toddouska 0:5045d2638c29 247
toddouska 0:5045d2638c29 248 if ((ret = RsaFunction(out, sz, out, &outLen, RSA_PUBLIC_ENCRYPT, key)) < 0)
toddouska 0:5045d2638c29 249 sz = ret;
toddouska 0:5045d2638c29 250
toddouska 0:5045d2638c29 251 return sz;
toddouska 0:5045d2638c29 252 }
toddouska 0:5045d2638c29 253
toddouska 0:5045d2638c29 254
toddouska 0:5045d2638c29 255 int RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key)
toddouska 0:5045d2638c29 256 {
toddouska 0:5045d2638c29 257 int plainLen, ret;
toddouska 0:5045d2638c29 258
toddouska 0:5045d2638c29 259 if ((ret = RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key))
toddouska 0:5045d2638c29 260 < 0) {
toddouska 0:5045d2638c29 261 return ret;
toddouska 0:5045d2638c29 262 }
toddouska 0:5045d2638c29 263
toddouska 0:5045d2638c29 264 plainLen = RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_2);
toddouska 0:5045d2638c29 265
toddouska 0:5045d2638c29 266 return plainLen;
toddouska 0:5045d2638c29 267 }
toddouska 0:5045d2638c29 268
toddouska 0:5045d2638c29 269 int RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
toddouska 0:5045d2638c29 270 RsaKey* key)
toddouska 0:5045d2638c29 271 {
toddouska 0:5045d2638c29 272 int plainLen, ret;
toddouska 0:5045d2638c29 273 byte* tmp;
toddouska 0:5045d2638c29 274 byte* pad = 0;
toddouska 0:5045d2638c29 275
toddouska 0:5045d2638c29 276 if ( !(tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA)) )
toddouska 0:5045d2638c29 277 return MEMORY_E;
toddouska 0:5045d2638c29 278
toddouska 0:5045d2638c29 279 XMEMCPY(tmp, in, inLen);
toddouska 0:5045d2638c29 280
toddouska 0:5045d2638c29 281 if ((ret = plainLen = RsaPrivateDecryptInline(tmp, inLen, &pad, key))
toddouska 0:5045d2638c29 282 < 0) {
toddouska 0:5045d2638c29 283 XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
toddouska 0:5045d2638c29 284 return ret;
toddouska 0:5045d2638c29 285 }
toddouska 0:5045d2638c29 286 XMEMCPY(out, pad, plainLen);
toddouska 0:5045d2638c29 287 XMEMSET(tmp, 0x00, inLen);
toddouska 0:5045d2638c29 288
toddouska 0:5045d2638c29 289 XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
toddouska 0:5045d2638c29 290 return plainLen;
toddouska 0:5045d2638c29 291 }
toddouska 0:5045d2638c29 292
toddouska 0:5045d2638c29 293
toddouska 0:5045d2638c29 294 /* for Rsa Verify */
toddouska 0:5045d2638c29 295 int RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
toddouska 0:5045d2638c29 296 {
toddouska 0:5045d2638c29 297 int plainLen, ret;
toddouska 0:5045d2638c29 298
toddouska 0:5045d2638c29 299 if ((ret = RsaFunction(in, inLen, in, &inLen, RSA_PUBLIC_DECRYPT, key))
toddouska 0:5045d2638c29 300 < 0) {
toddouska 0:5045d2638c29 301 return ret;
toddouska 0:5045d2638c29 302 }
toddouska 0:5045d2638c29 303
toddouska 0:5045d2638c29 304 plainLen = RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1);
toddouska 0:5045d2638c29 305
toddouska 0:5045d2638c29 306 return plainLen;
toddouska 0:5045d2638c29 307 }
toddouska 0:5045d2638c29 308
toddouska 0:5045d2638c29 309 int RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen,
toddouska 0:5045d2638c29 310 RsaKey* key)
toddouska 0:5045d2638c29 311 {
toddouska 0:5045d2638c29 312 int plainLen, ret;
toddouska 0:5045d2638c29 313 byte* tmp;
toddouska 0:5045d2638c29 314 byte* pad = 0;
toddouska 0:5045d2638c29 315
toddouska 0:5045d2638c29 316 if ( !(tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA)) )
toddouska 0:5045d2638c29 317 return MEMORY_E;
toddouska 0:5045d2638c29 318
toddouska 0:5045d2638c29 319 XMEMCPY(tmp, in, inLen);
toddouska 0:5045d2638c29 320
toddouska 0:5045d2638c29 321 if ((ret = plainLen = RsaSSL_VerifyInline(tmp, inLen, &pad, key))
toddouska 0:5045d2638c29 322 < 0) {
toddouska 0:5045d2638c29 323 XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
toddouska 0:5045d2638c29 324 return ret;
toddouska 0:5045d2638c29 325 }
toddouska 0:5045d2638c29 326
toddouska 0:5045d2638c29 327 XMEMCPY(out, pad, plainLen);
toddouska 0:5045d2638c29 328 XMEMSET(tmp, 0x00, inLen);
toddouska 0:5045d2638c29 329
toddouska 0:5045d2638c29 330 XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
toddouska 0:5045d2638c29 331 return plainLen;
toddouska 0:5045d2638c29 332 }
toddouska 0:5045d2638c29 333
toddouska 0:5045d2638c29 334
toddouska 0:5045d2638c29 335 /* for Rsa Sign */
toddouska 0:5045d2638c29 336 int RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen,
toddouska 0:5045d2638c29 337 RsaKey* key, RNG* rng)
toddouska 0:5045d2638c29 338 {
toddouska 0:5045d2638c29 339 int sz = mp_unsigned_bin_size(&key->n), ret;
toddouska 0:5045d2638c29 340
toddouska 0:5045d2638c29 341 if (sz > (int)outLen)
toddouska 0:5045d2638c29 342 return RSA_BUFFER_E;
toddouska 0:5045d2638c29 343
toddouska 0:5045d2638c29 344 if (inLen > (word32)(sz - RSA_MIN_PAD_SZ))
toddouska 0:5045d2638c29 345 return RSA_BUFFER_E;
toddouska 0:5045d2638c29 346
toddouska 0:5045d2638c29 347 RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_1, rng);
toddouska 0:5045d2638c29 348
toddouska 0:5045d2638c29 349 if ((ret = RsaFunction(out, sz, out, &outLen, RSA_PRIVATE_ENCRYPT,key)) < 0)
toddouska 0:5045d2638c29 350 sz = ret;
toddouska 0:5045d2638c29 351
toddouska 0:5045d2638c29 352 return sz;
toddouska 0:5045d2638c29 353 }
toddouska 0:5045d2638c29 354
toddouska 0:5045d2638c29 355
toddouska 0:5045d2638c29 356 int RsaEncryptSize(RsaKey* key)
toddouska 0:5045d2638c29 357 {
toddouska 0:5045d2638c29 358 return mp_unsigned_bin_size(&key->n);
toddouska 0:5045d2638c29 359 }
toddouska 0:5045d2638c29 360
toddouska 0:5045d2638c29 361
toddouska 0:5045d2638c29 362 #ifdef CYASSL_KEY_GEN
toddouska 0:5045d2638c29 363
toddouska 0:5045d2638c29 364 static const int USE_BBS = 1;
toddouska 0:5045d2638c29 365
toddouska 0:5045d2638c29 366 static int rand_prime(mp_int* N, int len, RNG* rng, void* heap)
toddouska 0:5045d2638c29 367 {
toddouska 0:5045d2638c29 368 int err, res, type;
toddouska 0:5045d2638c29 369 byte* buf;
toddouska 0:5045d2638c29 370
toddouska 0:5045d2638c29 371 if (N == NULL || rng == NULL)
toddouska 0:5045d2638c29 372 return -1;
toddouska 0:5045d2638c29 373
toddouska 0:5045d2638c29 374 /* get type */
toddouska 0:5045d2638c29 375 if (len < 0) {
toddouska 0:5045d2638c29 376 type = USE_BBS;
toddouska 0:5045d2638c29 377 len = -len;
toddouska 0:5045d2638c29 378 } else {
toddouska 0:5045d2638c29 379 type = 0;
toddouska 0:5045d2638c29 380 }
toddouska 0:5045d2638c29 381
toddouska 0:5045d2638c29 382 /* allow sizes between 2 and 512 bytes for a prime size */
toddouska 0:5045d2638c29 383 if (len < 2 || len > 512) {
toddouska 0:5045d2638c29 384 return -1;
toddouska 0:5045d2638c29 385 }
toddouska 0:5045d2638c29 386
toddouska 0:5045d2638c29 387 /* allocate buffer to work with */
toddouska 0:5045d2638c29 388 buf = XCALLOC(1, len, heap);
toddouska 0:5045d2638c29 389 if (buf == NULL) {
toddouska 0:5045d2638c29 390 return -1;
toddouska 0:5045d2638c29 391 }
toddouska 0:5045d2638c29 392
toddouska 0:5045d2638c29 393 do {
toddouska 0:5045d2638c29 394 #ifdef SHOW_GEN
toddouska 0:5045d2638c29 395 printf(".");
toddouska 0:5045d2638c29 396 fflush(stdout);
toddouska 0:5045d2638c29 397 #endif
toddouska 0:5045d2638c29 398 /* generate value */
toddouska 0:5045d2638c29 399 RNG_GenerateBlock(rng, buf, len);
toddouska 0:5045d2638c29 400
toddouska 0:5045d2638c29 401 /* munge bits */
toddouska 0:5045d2638c29 402 buf[0] |= 0x80 | 0x40;
toddouska 0:5045d2638c29 403 buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
toddouska 0:5045d2638c29 404
toddouska 0:5045d2638c29 405 /* load value */
toddouska 0:5045d2638c29 406 if ((err = mp_read_unsigned_bin(N, buf, len)) != MP_OKAY) {
toddouska 0:5045d2638c29 407 XFREE(buf, heap, DYNAMIC_TYPE_RSA);
toddouska 0:5045d2638c29 408 return err;
toddouska 0:5045d2638c29 409 }
toddouska 0:5045d2638c29 410
toddouska 0:5045d2638c29 411 /* test */
toddouska 0:5045d2638c29 412 if ((err = mp_prime_is_prime(N, 8, &res)) != MP_OKAY) {
toddouska 0:5045d2638c29 413 XFREE(buf, heap, DYNAMIC_TYPE_RSA);
toddouska 0:5045d2638c29 414 return err;
toddouska 0:5045d2638c29 415 }
toddouska 0:5045d2638c29 416 } while (res == MP_NO);
toddouska 0:5045d2638c29 417
toddouska 0:5045d2638c29 418 #ifdef LTC_CLEAN_STACK
toddouska 0:5045d2638c29 419 XMEMSET(buf, 0, len);
toddouska 0:5045d2638c29 420 #endif
toddouska 0:5045d2638c29 421
toddouska 0:5045d2638c29 422 XFREE(buf, heap, DYNAMIC_TYPE_RSA);
toddouska 0:5045d2638c29 423 return 0;
toddouska 0:5045d2638c29 424 }
toddouska 0:5045d2638c29 425
toddouska 0:5045d2638c29 426
toddouska 0:5045d2638c29 427 /* Make an RSA key for size bits, with e specified, 65537 is a good e */
toddouska 0:5045d2638c29 428 int MakeRsaKey(RsaKey* key, int size, long e, RNG* rng)
toddouska 0:5045d2638c29 429 {
toddouska 0:5045d2638c29 430 mp_int p, q, tmp1, tmp2, tmp3;
toddouska 0:5045d2638c29 431 int err;
toddouska 0:5045d2638c29 432
toddouska 0:5045d2638c29 433 if (key == NULL || rng == NULL)
toddouska 0:5045d2638c29 434 return -1;
toddouska 0:5045d2638c29 435
toddouska 0:5045d2638c29 436 if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE)
toddouska 0:5045d2638c29 437 return -1;
toddouska 0:5045d2638c29 438
toddouska 0:5045d2638c29 439 if (e < 3 || (e & 1) == 0)
toddouska 0:5045d2638c29 440 return -1;
toddouska 0:5045d2638c29 441
toddouska 0:5045d2638c29 442 if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY)
toddouska 0:5045d2638c29 443 return err;
toddouska 0:5045d2638c29 444
toddouska 0:5045d2638c29 445 err = mp_set_int(&tmp3, e);
toddouska 0:5045d2638c29 446
toddouska 0:5045d2638c29 447 /* make p */
toddouska 0:5045d2638c29 448 if (err == MP_OKAY) {
toddouska 0:5045d2638c29 449 do {
toddouska 0:5045d2638c29 450 err = rand_prime(&p, size/16, rng, key->heap); /* size in bytes/2 */
toddouska 0:5045d2638c29 451
toddouska 0:5045d2638c29 452 if (err == MP_OKAY)
toddouska 0:5045d2638c29 453 err = mp_sub_d(&p, 1, &tmp1); /* tmp1 = p-1 */
toddouska 0:5045d2638c29 454
toddouska 0:5045d2638c29 455 if (err == MP_OKAY)
toddouska 0:5045d2638c29 456 err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(p-1, e) */
toddouska 0:5045d2638c29 457 } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divdes p-1 */
toddouska 0:5045d2638c29 458 }
toddouska 0:5045d2638c29 459
toddouska 0:5045d2638c29 460 /* make q */
toddouska 0:5045d2638c29 461 if (err == MP_OKAY) {
toddouska 0:5045d2638c29 462 do {
toddouska 0:5045d2638c29 463 err = rand_prime(&q, size/16, rng, key->heap); /* size in bytes/2 */
toddouska 0:5045d2638c29 464
toddouska 0:5045d2638c29 465 if (err == MP_OKAY)
toddouska 0:5045d2638c29 466 err = mp_sub_d(&q, 1, &tmp1); /* tmp1 = q-1 */
toddouska 0:5045d2638c29 467
toddouska 0:5045d2638c29 468 if (err == MP_OKAY)
toddouska 0:5045d2638c29 469 err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(q-1, e) */
toddouska 0:5045d2638c29 470 } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divdes q-1 */
toddouska 0:5045d2638c29 471 }
toddouska 0:5045d2638c29 472
toddouska 0:5045d2638c29 473 if (err == MP_OKAY)
toddouska 0:5045d2638c29 474 err = mp_init_multi(&key->n, &key->e, &key->d, &key->p, &key->q, NULL);
toddouska 0:5045d2638c29 475
toddouska 0:5045d2638c29 476 if (err == MP_OKAY)
toddouska 0:5045d2638c29 477 err = mp_init_multi(&key->dP, &key->dP, &key->u, NULL, NULL, NULL);
toddouska 0:5045d2638c29 478
toddouska 0:5045d2638c29 479 if (err == MP_OKAY)
toddouska 0:5045d2638c29 480 err = mp_sub_d(&p, 1, &tmp2); /* tmp2 = p-1 */
toddouska 0:5045d2638c29 481
toddouska 0:5045d2638c29 482 if (err == MP_OKAY)
toddouska 0:5045d2638c29 483 err = mp_lcm(&tmp1, &tmp2, &tmp1); /* tmp1 = lcm(p-1, q-1),last loop */
toddouska 0:5045d2638c29 484
toddouska 0:5045d2638c29 485 /* make key */
toddouska 0:5045d2638c29 486 if (err == MP_OKAY)
toddouska 0:5045d2638c29 487 err = mp_set_int(&key->e, e); /* key->e = e */
toddouska 0:5045d2638c29 488
toddouska 0:5045d2638c29 489 if (err == MP_OKAY) /* key->d = 1/e mod lcm(p-1, q-1) */
toddouska 0:5045d2638c29 490 err = mp_invmod(&key->e, &tmp1, &key->d);
toddouska 0:5045d2638c29 491
toddouska 0:5045d2638c29 492 if (err == MP_OKAY)
toddouska 0:5045d2638c29 493 err = mp_mul(&p, &q, &key->n); /* key->n = pq */
toddouska 0:5045d2638c29 494
toddouska 0:5045d2638c29 495 if (err == MP_OKAY)
toddouska 0:5045d2638c29 496 err = mp_sub_d(&p, 1, &tmp1);
toddouska 0:5045d2638c29 497
toddouska 0:5045d2638c29 498 if (err == MP_OKAY)
toddouska 0:5045d2638c29 499 err = mp_sub_d(&q, 1, &tmp2);
toddouska 0:5045d2638c29 500
toddouska 0:5045d2638c29 501 if (err == MP_OKAY)
toddouska 0:5045d2638c29 502 err = mp_mod(&key->d, &tmp1, &key->dP);
toddouska 0:5045d2638c29 503
toddouska 0:5045d2638c29 504 if (err == MP_OKAY)
toddouska 0:5045d2638c29 505 err = mp_mod(&key->d, &tmp2, &key->dQ);
toddouska 0:5045d2638c29 506
toddouska 0:5045d2638c29 507 if (err == MP_OKAY)
toddouska 0:5045d2638c29 508 err = mp_invmod(&q, &p, &key->u);
toddouska 0:5045d2638c29 509
toddouska 0:5045d2638c29 510 if (err == MP_OKAY)
toddouska 0:5045d2638c29 511 err = mp_copy(&p, &key->p);
toddouska 0:5045d2638c29 512
toddouska 0:5045d2638c29 513 if (err == MP_OKAY)
toddouska 0:5045d2638c29 514 err = mp_copy(&q, &key->q);
toddouska 0:5045d2638c29 515
toddouska 0:5045d2638c29 516 if (err == MP_OKAY)
toddouska 0:5045d2638c29 517 key->type = RSA_PRIVATE;
toddouska 0:5045d2638c29 518
toddouska 0:5045d2638c29 519 mp_clear(&tmp3);
toddouska 0:5045d2638c29 520 mp_clear(&tmp2);
toddouska 0:5045d2638c29 521 mp_clear(&tmp1);
toddouska 0:5045d2638c29 522 mp_clear(&q);
toddouska 0:5045d2638c29 523 mp_clear(&p);
toddouska 0:5045d2638c29 524
toddouska 0:5045d2638c29 525 if (err != MP_OKAY) {
toddouska 0:5045d2638c29 526 FreeRsaKey(key);
toddouska 0:5045d2638c29 527 return err;
toddouska 0:5045d2638c29 528 }
toddouska 0:5045d2638c29 529
toddouska 0:5045d2638c29 530 return 0;
toddouska 0:5045d2638c29 531 }
toddouska 0:5045d2638c29 532
toddouska 0:5045d2638c29 533
toddouska 0:5045d2638c29 534 #endif /* CYASLS_KEY_GEN */
toddouska 0:5045d2638c29 535