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>
		
			
				
	
	
		
			214 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			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;
 | 
						|
}
 |