busybox/networking/tls_rsa.c
Denys Vlasenko 37bdd8f8cb tls: pstm code shrink
Optimize ABI calling convention and "dead code" cases where return value
is known to be always "success".

function                                             old     new   delta
pstm_mod                                             113    1227   +1114
pstm_exptmod                                        1463    1532     +69
pstm_montgomery_reduce                               381     393     +12
pstm_sqr_comba                                       478     487      +9
pstm_mul_comba                                       447     452      +5
der_binary_to_pstm                                    42      45      +3
pstm_count_bits                                       48      46      -2
pstm_clear                                            72      70      -2
pstm_clamp                                            57      55      -2
pstm_zero                                             38      34      -4
pstm_init_size                                        46      42      -4
pstm_init_for_read_unsigned_bin                       24      20      -4
pstm_grow                                             72      68      -4
pstm_unsigned_bin_size                                37      32      -5
pstm_cmp_mag                                          78      72      -6
pstm_copy                                             92      84      -8
pstm_mul_d                                           224     215      -9
pstm_rshd                                            104      94     -10
pstm_mul_2                                           156     146     -10
tls_handshake                                       2085    2072     -13
psRsaEncryptPub                                      421     408     -13
pstm_lshd                                            109      95     -14
pstm_cmp                                              54      39     -15
s_pstm_sub                                           228     212     -16
pstm_init_copy                                        72      52     -20
pstm_read_unsigned_bin                               109      88     -21
pstm_mulmod                                          120      99     -21
s_pstm_add                                           337     314     -23
pstm_add                                             108      84     -24
pstm_mul_2d                                          186     161     -25
pstm_sub                                             102      74     -28
pstm_to_unsigned_bin                                 151     120     -31
pstm_set                                              34       -     -34
pstm_div_2d                                          409     373     -36
pstm_init                                             42       -     -42
pstm_exch                                             50       -     -50
pstm_montgomery_setup                                 89       -     -89
pstm_2expt                                            96       -     -96
pstm_montgomery_calc_normalization                   140       -    -140
pstm_div                                            1522       -   -1522
------------------------------------------------------------------------------
(add/remove: 0/7 grow/shrink: 6/27 up/down: 1212/-2343)     Total: -1131 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2019-01-01 15:40:43 +01:00

214 lines
5.4 KiB
C

/*
* 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(&tmpa);
pstm_clear(&tmpb);
}
pstm_clear(&tmp);
return res;
}
int32 FAST_FUNC 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;
}