Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | /*
* Copyright (C) 2017 Denys Vlasenko
*
* Licensed under GPLv2, see file LICENSE in this source tree.
*/
#include "tls.h"
/* The code below is taken from parts of
* matrixssl-3-7-2b-open/crypto/pubkey/pkcs.c
* matrixssl-3-7-2b-open/crypto/pubkey/rsa.c
* and (so far) almost not modified. Changes are flagged with //bbox
*/
#define pkcs1Pad(in, inlen, out, outlen, cryptType, userPtr) \
pkcs1Pad(in, inlen, out, outlen, cryptType)
static //bbox
int32 pkcs1Pad(unsigned char *in, uint32 inlen, unsigned char *out,
uint32 outlen, int32 cryptType, void *userPtr)
{
unsigned char *c;
int32 randomLen;
randomLen = outlen - 3 - inlen;
if (randomLen < 8) {
psTraceCrypto("pkcs1Pad failure\n");
return PS_LIMIT_FAIL;
}
c = out;
*c = 0x00;
c++;
*c = (unsigned char)cryptType;
c++;
if (cryptType == PUBKEY_TYPE) {
while (randomLen-- > 0) {
*c++ = 0xFF;
}
} else {
if (matrixCryptoGetPrngData(c, (uint32)randomLen, userPtr) < 0) {
return PS_PLATFORM_FAIL;
}
/*
SECURITY: Read through the random data and change all 0x0 to 0x01.
This is per spec that no random bytes should be 0
*/
while (randomLen-- > 0) {
if (*c == 0x0) {
*c = 0x01;
}
c++;
}
}
*c = 0x00;
c++;
memcpy(c, in, inlen);
return outlen;
}
#define psRsaCrypt(pool, in, inlen, out, outlen, key, type, data) \
psRsaCrypt( in, inlen, out, outlen, key, type)
static //bbox
int32 psRsaCrypt(psPool_t *pool, const unsigned char *in, uint32 inlen,
unsigned char *out, uint32 *outlen, psRsaKey_t *key, int32 type,
void *data)
{
pstm_int tmp, tmpa, tmpb;
int32 res;
uint32 x;
//bbox
// if (in == NULL || out == NULL || outlen == NULL || key == NULL) {
// psTraceCrypto("NULL parameter error in psRsaCrypt\n");
// return PS_ARG_FAIL;
// }
tmp.dp = tmpa.dp = tmpb.dp = NULL;
/* Init and copy into tmp */
if (pstm_init_for_read_unsigned_bin(pool, &tmp, inlen + sizeof(pstm_digit))
!= PS_SUCCESS) {
return PS_FAILURE;
}
if (pstm_read_unsigned_bin(&tmp, (unsigned char *)in, inlen) != PS_SUCCESS){
pstm_clear(&tmp);
return PS_FAILURE;
}
/* Sanity check on the input */
if (pstm_cmp(&key->N, &tmp) == PSTM_LT) {
res = PS_LIMIT_FAIL;
goto done;
}
if (type == PRIVKEY_TYPE) {
if (key->optimized) {
if (pstm_init_size(pool, &tmpa, key->p.alloc) != PS_SUCCESS) {
res = PS_FAILURE;
goto done;
}
if (pstm_init_size(pool, &tmpb, key->q.alloc) != PS_SUCCESS) {
pstm_clear(&tmpa);
res = PS_FAILURE;
goto done;
}
if (pstm_exptmod(pool, &tmp, &key->dP, &key->p, &tmpa) !=
PS_SUCCESS) {
psTraceCrypto("decrypt error: pstm_exptmod dP, p\n");
goto error;
}
if (pstm_exptmod(pool, &tmp, &key->dQ, &key->q, &tmpb) !=
PS_SUCCESS) {
psTraceCrypto("decrypt error: pstm_exptmod dQ, q\n");
goto error;
}
if (pstm_sub(&tmpa, &tmpb, &tmp) != PS_SUCCESS) {
psTraceCrypto("decrypt error: sub tmpb, tmp\n");
goto error;
}
if (pstm_mulmod(pool, &tmp, &key->qP, &key->p, &tmp) != PS_SUCCESS) {
psTraceCrypto("decrypt error: pstm_mulmod qP, p\n");
goto error;
}
if (pstm_mul_comba(pool, &tmp, &key->q, &tmp, NULL, 0)
!= PS_SUCCESS){
psTraceCrypto("decrypt error: pstm_mul q \n");
goto error;
}
if (pstm_add(&tmp, &tmpb, &tmp) != PS_SUCCESS) {
psTraceCrypto("decrypt error: pstm_add tmp \n");
goto error;
}
} else {
if (pstm_exptmod(pool, &tmp, &key->d, &key->N, &tmp) !=
PS_SUCCESS) {
psTraceCrypto("psRsaCrypt error: pstm_exptmod\n");
goto error;
}
}
} else if (type == PUBKEY_TYPE) {
if (pstm_exptmod(pool, &tmp, &key->e, &key->N, &tmp) != PS_SUCCESS) {
psTraceCrypto("psRsaCrypt error: pstm_exptmod\n");
goto error;
}
} else {
psTraceCrypto("psRsaCrypt error: invalid type param\n");
goto error;
}
/* Read it back */
x = pstm_unsigned_bin_size(&key->N);
if ((uint32)x > *outlen) {
res = -1;
psTraceCrypto("psRsaCrypt error: pstm_unsigned_bin_size\n");
goto done;
}
/* We want the encrypted value to always be the key size. Pad with 0x0 */
while ((uint32)x < (unsigned long)key->size) {
*out++ = 0x0;
x++;
}
*outlen = x;
/* Convert it */
memset(out, 0x0, x);
if (pstm_to_unsigned_bin(pool, &tmp, out+(x-pstm_unsigned_bin_size(&tmp)))
!= PS_SUCCESS) {
psTraceCrypto("psRsaCrypt error: pstm_to_unsigned_bin\n");
goto error;
}
/* Clean up and return */
res = PS_SUCCESS;
goto done;
error:
res = PS_FAILURE;
done:
if (type == PRIVKEY_TYPE && key->optimized) {
pstm_clear_multi(&tmpa, &tmpb, NULL, NULL, NULL, NULL, NULL, NULL);
}
pstm_clear(&tmp);
return res;
}
int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key,
unsigned char *in, uint32 inlen,
unsigned char *out, uint32 outlen, void *data)
{
int32 err;
uint32 size;
size = key->size;
if (outlen < size) {
//bbox psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub\n");
bb_error_msg_and_die("RSA crypt outlen:%d < size:%d", outlen, size);
return PS_ARG_FAIL;
}
if ((err = pkcs1Pad(in, inlen, out, size, PRIVKEY_TYPE, data))
< PS_SUCCESS) {
psTraceCrypto("Error padding psRsaEncryptPub. Likely data too long\n");
return err;
}
if ((err = psRsaCrypt(pool, out, size, out, (uint32*)&outlen, key,
PUBKEY_TYPE, data)) < PS_SUCCESS) {
psTraceCrypto("Error performing psRsaEncryptPub\n");
return err;
}
if (outlen != size) {
psTraceCrypto("Encrypted size error in psRsaEncryptPub\n");
return PS_FAILURE;
}
return size;
}
|