MatrixSSL 3.8.3 Open

This commit is contained in:
J Harper
2016-04-15 15:12:52 -07:00
parent 2a1158838b
commit 5b09e8e149
315 changed files with 94773 additions and 0 deletions

447
crypto/pubkey/dh.c Normal file
View File

@@ -0,0 +1,447 @@
/**
* @file dh.c
* @version $Format:%h%d$
*
* Diffie-Hellman.
*/
/*
* Copyright (c) 2013-2016 INSIDE Secure Corporation
* Copyright (c) PeerSec Networks, 2002-2011
* All Rights Reserved
*
* The latest version of this code is available at http://www.matrixssl.org
*
* This software is open source; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This General Public License does NOT permit incorporating this software
* into proprietary programs. If you are unable to comply with the GPL, a
* commercial license for this software may be purchased from INSIDE at
* http://www.insidesecure.com/
*
* This program is distributed in WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* http://www.gnu.org/copyleft/gpl.html
*/
/******************************************************************************/
#include "../cryptoApi.h"
#ifdef USE_MATRIX_DH
/******************************************************************************/
void psDhClearKey(psDhKey_t *key)
{
psAssert(key);
pstm_clear(&key->priv);
pstm_clear(&key->pub);
key->type = 0;
}
uint16_t psDhSize(const psDhKey_t *key)
{
return key->size;
}
/******************************************************************************/
/**
Parse ASN.1 encoded DH parameters.
DHParameter ::= SEQUENCE {
prime INTEGER, -- p
base INTEGER, -- g
privateValueLength INTEGER OPTIONAL
}
@note privateValueLength field unsupported
@param pool Memory pool
@param[in] dhBin Pointer to buffer containing ASN.1 format parameters
@param[in] dhBinLen Length in bytes of 'dhBin'
@param[in,out] params Allocated parameter structure to receive parsed
params.
@return < on error.
*/
int32_t pkcs3ParseDhParamBin(psPool_t *pool, const unsigned char *dhBin,
uint16_t dhBinLen, psDhParams_t *params)
{
const unsigned char *c, *end;
uint16_t baseLen;
if (!params || !dhBin) {
return PS_ARG_FAIL;
}
end = dhBin + dhBinLen;
c = dhBin;
if (getAsnSequence(&c, (uint16_t)(end - c), &baseLen) < 0) {
return PS_PARSE_FAIL;
}
/* Parse the DH prime value and validate against minimum length */
if (pstm_read_asn(pool, &c, (uint16_t)(end - c), &params->p) < 0) {
goto L_ERR;
}
params->size = pstm_unsigned_bin_size(&params->p);
if (params->size < (MIN_DH_BITS / 8)) {
psTraceIntCrypto("Unsupported DH prime size %hu\n", params->size);
goto L_ERR;
}
/* The DH base parameter is typically small (usually value 2 or 5),
so we don't validate against a minimum length */
if (pstm_read_asn(pool, &c, (uint16_t)(end - c), &params->g) < 0) {
goto L_ERR;
}
if (end != c) {
psTraceCrypto("Unsupported DHParameter Format\n");
goto L_ERR;
}
params->pool = pool;
return PS_SUCCESS;
L_ERR:
pstm_clear(&params->g);
pstm_clear(&params->p);
params->pool = NULL;
params->size = 0;
return PS_PARSE_FAIL;
}
/**
Clear DH params.
@param[out] params Pointer to allocated DH params to clear.
@note Caller is responsible for freeing memory associated with 'params',
if appropriate.
*/
void pkcs3ClearDhParams(psDhParams_t *params)
{
if (params == NULL) {
return;
}
pstm_clear(&params->g);
pstm_clear(&params->p);
params->size = 0;
params->pool = NULL;
}
/**
Allocate and populate buffers for DH prime and base values.
@param pool Memory pool
@param[in] params DH params to export
@param[out] pp On success, will point to an allocated memory buffer
containing the DH params prime value.
@param[out] pLen Pointer to value to receive length of 'pp' in bytes
@param[out] pg On success, will point to an allocated memory buffer
containing the DH params generator/base value.
@param[out] gLen Pointer to value to receive length of 'pg' in bytes
@return < 0 on failure
@post On success, the buffers pointed to by 'pp' and 'pg' are allocated
by this API and must be freed by the caller.
*/
int32_t psDhExportParameters(psPool_t *pool,
const psDhParams_t *params,
unsigned char **pp, uint16_t *pLen,
unsigned char **pg, uint16_t *gLen)
{
uint16_t pl, gl;
unsigned char *p, *g;
pl = pstm_unsigned_bin_size(&params->p);
gl = pstm_unsigned_bin_size(&params->g);
if ((p = psMalloc(pool, pl)) == NULL) {
psError("Memory allocation error in psDhExportParameters\n");
return PS_MEM_FAIL;
}
if ((g = psMalloc(pool, gl)) == NULL) {
psError("Memory allocation error in psDhExportParameters\n");
psFree(p, pool);
return PS_MEM_FAIL;
}
if (pstm_to_unsigned_bin(pool, &params->p, p) < 0 ||
pstm_to_unsigned_bin(pool, &params->g, g) < 0) {
psFree(p, pool);
psFree(g, pool);
return PS_FAIL;
}
*pLen = pl;
*gLen = gl;
*pp = p;
*pg = g;
return PS_SUCCESS;
}
/******************************************************************************/
/**
Import a public DH key in raw (wire) format to a psDhKey_t struct.
@param pool Memory pool
@param[in] in Pointer to buffer containing raw public DH key
@param[in] inlen Length in bytes of 'in'
@param[out] key Pointer to allocated key to be initialized with raw
DH value from 'in'.
@return < on failure
*/
int32_t psDhImportPubKey(psPool_t *pool,
const unsigned char *in, uint16_t inlen,
psDhKey_t *key)
{
int32_t rc;
memset(&key->priv, 0x0, sizeof(psDhKey_t));
if ((rc = pstm_init_for_read_unsigned_bin(pool, &key->pub, inlen)) < 0) {
return rc;
}
if ((rc = pstm_read_unsigned_bin(&key->pub, in, inlen)) < 0) {
pstm_clear(&key->pub);
return rc;
}
key->size = inlen;
key->type = PS_PUBKEY;
return PS_SUCCESS;
}
/**
Export a public psDhKey_t struct to a raw binary format.
@param pool Memory pool
@param[in] key Pointer to DH key to export
@param[out] out Pointer to buffer to write raw public DH key
@param[in,out] outlen On input, the number of bytes available in 'out',
on successful return, the number of bytes written to 'out'.
@return < on failure
*/
int32_t psDhExportPubKey(psPool_t *pool, const psDhKey_t *key,
unsigned char *out, uint16_t *outlen)
{
unsigned char *c;
int16_t pad;
int32_t rc;
if (*outlen < key->size) {
return PS_ARG_FAIL;
}
c = out;
pad = key->size - pstm_unsigned_bin_size(&key->pub);
if (pad > 0) {
memset(c, 0x0, pad);
c += pad;
} else if (pad < 0) {
return PS_FAIL;
}
if ((rc = pstm_to_unsigned_bin(pool, &key->pub, c)) < 0) {
return rc;
}
*outlen = key->size;
return PS_SUCCESS;
}
/******************************************************************************/
/**
Generate a DH key given the parameters.
*/
int32_t psDhGenKey(psPool_t *pool, uint16_t keysize,
const unsigned char *pBin, uint16_t pLen,
const unsigned char *gBin, uint16_t gLen,
psDhKey_t *key, void *usrData)
{
int32_t rc;
pstm_int p, g;
/* Convert the p and g into ints and make keys */
if ((rc = pstm_init_for_read_unsigned_bin(pool, &p, pLen)) != PS_SUCCESS) {
return rc;
}
if ((rc = pstm_init_for_read_unsigned_bin(pool, &g, gLen)) != PS_SUCCESS) {
pstm_clear(&p);
return rc;
}
if ((rc = pstm_read_unsigned_bin(&p, pBin, pLen)) != PS_SUCCESS) {
goto error;
}
if ((rc = pstm_read_unsigned_bin(&g, gBin, gLen)) != PS_SUCCESS) {
goto error;
}
rc = psDhGenKeyInts(pool, keysize, &p, &g, key, usrData);
error:
pstm_clear(&p);
pstm_clear(&g);
return rc;
}
/******************************************************************************/
/**
Does the actual key generation given p and g.
*/
#define DH_KEYGEN_SANITY 256
int32_t psDhGenKeyInts(psPool_t *pool, uint16_t keysize,
const pstm_int *p, const pstm_int *g,
psDhKey_t *key, void *usrData)
{
unsigned char *buf = NULL;
int32_t err, i;
uint16_t privsize;
if (key == NULL) {
return PS_ARG_FAIL;
}
privsize = keysize;
#ifndef USE_LARGE_DH_PRIVATE_KEYS
/*
The mapping between DH prime field size and key size follows
NIST SP 800-57 Part 1 for the common sizes, and for unusual
sizes the key size is intentionally rounded up.
The private key size must never be larger than prime size.
*/
if (keysize >= 160 / 8 && keysize <= 1024 / 8) {
privsize = 160 / 8;
} else if (keysize > 1024 / 8 && keysize <= 2048 / 8) {
privsize = 224 / 8;
} else if (keysize > 2048 / 8 && keysize <= 3072 / 8) {
privsize = 256 / 8;
} else if (keysize > 3072 / 8 && keysize <= 7680 / 8) {
privsize = 384 / 8;
} else if (keysize > 7680 / 8 && keysize <= 15360 / 8) {
privsize = 256 / 8;
}
#endif /* USE_LARGE_DH_PRIVATE_KEYS */
key->size = keysize;
buf = psMalloc(pool, privsize);
if (buf == NULL) {
psError("malloc error in psDhMakeKey\n");
return PS_MEM_FAIL;
}
if ((err = pstm_init_for_read_unsigned_bin(pool, &key->priv, privsize))
!= PS_SUCCESS) {
goto error;
}
for (i = 0; i < DH_KEYGEN_SANITY; i++) {
if ((err = matrixCryptoGetPrngData(buf, privsize, usrData)) < 0) {
goto error;
}
/* Load the random bytes as the private key */
if ((err = pstm_read_unsigned_bin(&key->priv, buf, privsize))
!= PS_SUCCESS) {
goto error;
}
/* Test (1 < key < p), usually succeeds right away */
if (pstm_cmp_d(&key->priv, 1) == PSTM_GT &&
pstm_cmp(&key->priv, p) == PSTM_LT) {
break; /* found one */
}
}
if (i == DH_KEYGEN_SANITY) {
psTraceCrypto("DH private key could not be generated\n");
err = PS_PLATFORM_FAIL;
goto error;
}
/* Have the private key, now calculate the public part */
if ((err = pstm_init_size(pool, &key->pub, (p->used * 2) + 1))
!= PS_SUCCESS) {
pstm_clear(&key->priv);
goto error;
}
if ((err = pstm_exptmod(pool, g, &key->priv, p, &key->pub)) !=
PS_SUCCESS) {
goto error;
}
key->type = PS_PRIVKEY;
err = PS_SUCCESS;
goto done;
error:
pstm_clear(&key->priv);
pstm_clear(&key->pub);
done:
if (buf) {
memzero_s(buf, privsize);
psFree(buf, pool);
}
return err;
}
/******************************************************************************/
/**
Create the DH premaster secret.
@param[in] privKey The private DH key in the pair
@param[in] pubKey The public DH key in the pair
@param[in] pBin The DH Param Prime value
@param[in] pBinLen The length in bytes if 'pBin'
@param[out] out Buffer to write the shared secret
@param[in,out] outlen On input, the available space in 'out', on
successful return, the number of bytes written to 'out'.
*/
int32_t psDhGenSharedSecret(psPool_t *pool,
const psDhKey_t *privKey, const psDhKey_t *pubKey,
const unsigned char *pBin, uint16_t pBinLen,
unsigned char *out, uint16_t *outlen, void *usrData)
{
pstm_int tmp, p;
uint16_t x;
int32_t err;
/* Verify the privKey is a private type. pubKey param can be either */
if (privKey->type != PS_PRIVKEY) {
psTraceCrypto("Bad private key format for DH premaster\n");
return PS_ARG_FAIL;
}
/* compute y^x mod p */
if ((err = pstm_init(pool, &tmp)) != PS_SUCCESS) {
return err;
}
if ((err = pstm_init_for_read_unsigned_bin(pool, &p, pBinLen)) != PS_SUCCESS) {
return err;
}
if ((err = pstm_read_unsigned_bin(&p, pBin, pBinLen)) != PS_SUCCESS) {
goto error;
}
if ((err = pstm_exptmod(pool, &pubKey->pub, &privKey->priv, &p,
&tmp)) != PS_SUCCESS) {
goto error;
}
/* enough space for output? */
x = (unsigned long)pstm_unsigned_bin_size(&tmp);
if (*outlen < x) {
psTraceCrypto("Overflow in DH premaster generation\n");
err = PS_LIMIT_FAIL;
goto error;
}
/* It is possible to have a key size smaller than we expect */
*outlen = x;
if ((err = pstm_to_unsigned_bin(pool, &tmp, out)) < 0) {
goto error;
}
err = PS_SUCCESS;
error:
pstm_clear(&p);
pstm_clear(&tmp);
return err;
}
#endif /* USE_MATRIX_DH */
/******************************************************************************/

2695
crypto/pubkey/ecc.c Normal file

File diff suppressed because it is too large Load Diff

184
crypto/pubkey/pubkey.c Normal file
View File

@@ -0,0 +1,184 @@
/**
* @file pubkey.c
* @version $Format:%h%d$
*
* Public and Private key operations shared by crypto implementations.
*/
/*
* Copyright (c) 2013-2016 INSIDE Secure Corporation
* Copyright (c) PeerSec Networks, 2002-2011
* All Rights Reserved
*
* The latest version of this code is available at http://www.matrixssl.org
*
* This software is open source; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This General Public License does NOT permit incorporating this software
* into proprietary programs. If you are unable to comply with the GPL, a
* commercial license for this software may be purchased from INSIDE at
* http://www.insidesecure.com/
*
* This program is distributed in WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* http://www.gnu.org/copyleft/gpl.html
*/
/******************************************************************************/
#include "../cryptoApi.h"
#if defined(USE_RSA) || defined(USE_ECC)
/******************************************************************************/
int32_t psInitPubKey(psPool_t *pool, psPubKey_t *key, uint8_t type)
{
if (!key) {
return PS_ARG_FAIL;
}
switch (type) {
#ifdef USE_RSA
case PS_RSA:
psRsaInitKey(pool, &key->key.rsa);
break;
#endif
#ifdef USE_ECC
case PS_ECC:
psEccInitKey(pool, &key->key.ecc, NULL);
break;
#endif
default:
break;
}
key->pool = pool;
key->type = type;
key->keysize = 0;
return PS_SUCCESS;
}
/******************************************************************************/
void psClearPubKey(psPubKey_t *key)
{
if (!key) {
return;
}
switch (key->type) {
#ifdef USE_RSA
case PS_RSA:
psRsaClearKey(&key->key.rsa);
break;
#endif
#ifdef USE_ECC
case PS_ECC:
psEccClearKey(&key->key.ecc);
break;
#endif
default:
break;
}
key->pool = NULL;
key->keysize = 0;
key->type = 0;
}
int32_t psNewPubKey(psPool_t *pool, uint8_t type, psPubKey_t **key)
{
int32_t rc;
if ((*key = psMalloc(pool, sizeof(psPubKey_t))) == NULL) {
return PS_MEM_FAIL;
}
if ((rc = psInitPubKey(pool, *key, type)) < 0) {
psFree(*key, pool);
}
return rc;
}
void psDeletePubKey(psPubKey_t **key)
{
psClearPubKey(*key);
psFree(*key, NULL);
*key = NULL;
}
#ifdef MATRIX_USE_FILE_SYSTEM
#if defined(USE_ECC) && defined(USE_RSA)
/* Trial and error private key parse for when ECC or RSA is unknown.
pemOrDer should be 1 if PEM
Return codes:
1 RSA key
2 ECC key
-1 error
*/
int32_t psParseUnknownPrivKey(psPool_t *pool, int pemOrDer, char *keyfile,
char *password, psPubKey_t *privkey)
{
psRsaKey_t *rsakey;
psEccKey_t *ecckey;
int keytype;
unsigned char *keyBuf;
int32 keyBufLen;
privkey->keysize = 0;
rsakey = &privkey->key.rsa;
ecckey = &privkey->key.ecc;
if (pemOrDer == 1) {
if (pkcs1ParsePrivFile(pool, keyfile, password, rsakey)
< PS_SUCCESS) {
if (psEccParsePrivFile(pool, keyfile, password, ecckey)
< PS_SUCCESS) {
psTraceStrCrypto("Unable to parse private key file %s\n",
keyfile);
return -1;
}
keytype = 2;
} else {
keytype = 1;
}
} else {
if (psGetFileBuf(pool, keyfile, &keyBuf, &keyBufLen) < PS_SUCCESS) {
psTraceStrCrypto("Unable to open private key file %s\n", keyfile);
return -1;
}
if (psRsaParsePkcs1PrivKey(pool, keyBuf, keyBufLen, rsakey)
< PS_SUCCESS) {
if (psEccParsePrivKey(pool, keyBuf, keyBufLen, ecckey, NULL)
< PS_SUCCESS) {
psTraceCrypto("Unable to parse private key\n");
psFree(keyBuf, pool);
return -1;
}
keytype = 2;
} else {
keytype = 1;
}
psFree(keyBuf, pool);
}
if (keytype == 1) {
privkey->type = PS_RSA;
privkey->keysize = psRsaSize(&privkey->key.rsa);
} else {
privkey->type = PS_ECC;
privkey->keysize = psEccSize(&privkey->key.ecc);
}
privkey->pool = pool;
return keytype;
}
#endif /* USE_ECC && USE_RSA */
#endif /* MATRIX_USE_FILE_SYSTEM */
/******************************************************************************/
#endif /* USE_RSA || USE_ECC */

208
crypto/pubkey/pubkey.h Normal file
View File

@@ -0,0 +1,208 @@
/**
* @file pubkey.h
* @version $Format:%h%d$
*
* Public and Private key header.
*/
/*
* Copyright (c) 2013-2016 INSIDE Secure Corporation
* Copyright (c) PeerSec Networks, 2002-2011
* All Rights Reserved
*
* The latest version of this code is available at http://www.matrixssl.org
*
* This software is open source; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This General Public License does NOT permit incorporating this software
* into proprietary programs. If you are unable to comply with the GPL, a
* commercial license for this software may be purchased from INSIDE at
* http://www.insidesecure.com/
*
* This program is distributed in WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* http://www.gnu.org/copyleft/gpl.html
*/
/******************************************************************************/
#ifndef _h_PS_PUBKEY
#define _h_PS_PUBKEY
/******************************************************************************/
#include "pubkey_matrix.h"
#ifdef USE_OPENSSL_CRYPTO
#include "pubkey_openssl.h"
#endif
/******************************************************************************/
#ifdef USE_RSA
/**
The included pubkey_* header must define:
typedef ... psRsaKey_t;
and
PS_RSA_STATIC_INIT
*/
#ifndef PS_RSA_STATIC_INIT
#define PS_RSA_STATIC_INIT { .size = NULL }
#endif
#endif /* USE_RSA */
/******************************************************************************/
#ifdef USE_ECC
#define ECC_MAXSIZE 132 /* max private key size */
/* NOTE: In MatrixSSL usage, the ecFlags are 24 bits only */
#define IS_SECP192R1 0x00000001
#define IS_SECP224R1 0x00000002
#define IS_SECP256R1 0x00000004
#define IS_SECP384R1 0x00000008
#define IS_SECP521R1 0x00000010
/* WARNING: Public points on Brainpool curves are not validated */
#define IS_BRAIN224R1 0x00010000
#define IS_BRAIN256R1 0x00020000
#define IS_BRAIN384R1 0x00040000
#define IS_BRAIN512R1 0x00080000
/* TLS needs one bit of info (last bit) */
#define IS_RECVD_EXT 0x00800000
/**
@see https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
*/
enum {
IANA_SECP192R1 = 19,
IANA_SECP224R1 = 21,
IANA_SECP256R1 = 23,
IANA_SECP384R1,
IANA_SECP521R1,
IANA_BRAIN256R1,
IANA_BRAIN384R1,
IANA_BRAIN512R1,
IANA_BRAIN224R1 = 255 /**< @note this is not defined by IANA */
};
/**
@see ANSI X9.62 or X9.63
*/
enum {
ANSI_INFINITY = 0,
ANSI_COMPRESSED0 = 2,
ANSI_COMPRESSED1,
ANSI_UNCOMPRESSED,
ANSI_HYBRID0 = 6,
ANSI_HYBRID1
};
/**
The included pubkey_* header must define the following.
typedef ... psEccCurve_t;
typedef ... psEccPoint_t;
typedef ... psEccKey_t;
and
PS_ECC_STATIC_INIT
and implement the following functions.
*/
#ifndef PS_ECC_STATIC_INIT
#define PS_ECC_STATIC_INIT { .type = 0 }
#endif
extern void psGetEccCurveIdList(unsigned char *curveList, uint8_t *len);
extern void userSuppliedEccList(unsigned char *curveList, uint8_t *len,
uint32_t curves);
extern uint32_t compiledInEcFlags(void);
extern int32_t getEcPubKey(psPool_t *pool, const unsigned char **pp, uint16_t len,
psEccKey_t *pubKey, unsigned char sha1KeyHash[SHA1_HASH_SIZE]);
extern int32_t getEccParamById(uint16_t curveId, const psEccCurve_t **curve);
extern int32_t getEccParamByName(const char *curveName,
const psEccCurve_t **curve);
extern int32_t getEccParamByOid(uint32_t oid, const psEccCurve_t **curve);
#endif
/******************************************************************************/
#ifdef USE_DH
/**
The included pubkey_* header must define:
typedef ... psDhParams_t;
typedef ... psDhKey_t;
and
PS_DH_STATIC_INIT
*/
#ifndef PS_DH_STATIC_INIT
#define PS_DH_STATIC_INIT { .type = 0 }
#endif
#endif
/******************************************************************************/
/** Public or private key */
enum PACKED {
PS_PUBKEY = 1,
PS_PRIVKEY
};
/** Public Key types for psPubKey_t */
enum PACKED {
PS_NONE = 0,
PS_RSA,
PS_ECC,
PS_DH
};
/** Signature types */
enum PACKED {
RSA_TYPE_SIG = 5,
ECDSA_TYPE_SIG,
RSAPSS_TYPE_SIG
};
/**
Univeral public key type.
The pubKey name comes from the generic public-key crypto terminology and
does not mean these key are restricted to the public side only. These
may be private keys.
*/
typedef struct {
#if defined(USE_RSA) || defined(USE_ECC)
union {
#ifdef USE_RSA
psRsaKey_t rsa;
#endif
#ifdef USE_ECC
psEccKey_t ecc;
#endif
#ifdef USE_DH
psDhKey_t dh;
#endif
} key;
#endif
psPool_t *pool;
uint16_t keysize; /* in bytes. 512 max for RSA 4096 */
uint8_t type; /* PS_RSA, PS_ECC, PS_DH */
} psPubKey_t;
extern int32_t pkcs1Pad(const unsigned char *in, uint16_t inlen,
unsigned char *out, uint16_t outlen,
uint8_t cryptType, void *userPtr);
extern int32_t pkcs1Unpad(const unsigned char *in, uint16_t inlen,
unsigned char *out, uint16_t outlen,
uint8_t decryptType);
/******************************************************************************/
#endif /* _h_PS_PUBKEY */

View File

@@ -0,0 +1,117 @@
/**
* @file pubkey_matrix.h
* @version $Format:%h%d$
*
* MatrixSSL Crypto Implementation for RSA, DH and ECC.
*/
/*
* Copyright (c) 2013-2016 INSIDE Secure Corporation
* Copyright (c) PeerSec Networks, 2002-2011
* All Rights Reserved
*
* The latest version of this code is available at http://www.matrixssl.org
*
* This software is open source; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This General Public License does NOT permit incorporating this software
* into proprietary programs. If you are unable to comply with the GPL, a
* commercial license for this software may be purchased from INSIDE at
* http://www.insidesecure.com/
*
* This program is distributed in WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* http://www.gnu.org/copyleft/gpl.html
*/
/******************************************************************************/
#ifndef _h_MATRIX_PUBKEY
#define _h_MATRIX_PUBKEY
/******************************************************************************/
#ifdef USE_MATRIX_RSA
typedef struct {
pstm_int e, d, N, qP, dP, dQ, p, q;
psPool_t *pool;
uint16_t size; /* Size of the key in bytes */
uint8_t optimized; /* Set if optimized */
} psRsaKey_t;
#endif
/******************************************************************************/
#ifdef USE_MATRIX_ECC
/**
An ECC curve.
Including size, name, and domain parameters.
*/
typedef struct {
uint8_t size; /**< The size of the curve in octets */
uint16_t curveId; /**< IANA named curve id for TLS use */
uint8_t isOptimized; /**< 1 if optimized with field param A=-3. */
uint32_t OIDsum; /**< Internal Matrix OID */
const char *name; /**< name of curve */
/* These below constitute the domain parameters */
const char *prime; /**< prime defining the curve field (ascii hex) */
const char *A; /**< The field's A param (ascii hex) */
const char *B; /**< The field's B param (ascii hex) */
const char *order; /**< The order of the curve (ascii hex) */
const char *Gx; /**< The x coordinate of the base point (ascii hex) */
const char *Gy; /**< The y coordinate of the base point (ascii hex) */
} psEccCurve_t;
/**
A point on a ECC curve, stored in Jacbobian format such that
(x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine.
*/
typedef struct {
pstm_int x; /* The x co-ordinate */
pstm_int y; /* The y co-ordinate */
pstm_int z; /* The z co-ordinate */
psPool_t *pool;
} psEccPoint_t;
typedef struct {
pstm_int k; /* The private key */
psEccPoint_t pubkey; /* The public key */
const psEccCurve_t *curve; /* pointer to named curve */
psPool_t *pool;
uint8_t type; /* Type of key, PS_PRIVKEY or PS_PUBKEY */
} psEccKey_t;
#endif
/******************************************************************************/
#ifdef USE_MATRIX_DH
typedef struct {
pstm_int p; /* The Prime value */
pstm_int g; /* The Generator/Base value */
psPool_t *pool;
uint16_t size; /* Size of 'p' in bytes */
} psDhParams_t;
typedef struct {
pstm_int priv, pub;
uint16_t size;
uint8_t type; /* PS_PRIVKEY or PS_PUBKEY */
} psDhKey_t;
#endif
/******************************************************************************/
#endif /* _h_MATRIX_PUBKEY */

View File

@@ -0,0 +1,66 @@
/**
* @file pubkey_openssl.h
* @version $Format:%h%d$
*
* OpenSSL Layer for RSA, DH and ECC.
*/
/*
* Copyright (c) 2013-2016 INSIDE Secure Corporation
* Copyright (c) PeerSec Networks, 2002-2011
* All Rights Reserved
*
* The latest version of this code is available at http://www.matrixssl.org
*
* This software is open source; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This General Public License does NOT permit incorporating this software
* into proprietary programs. If you are unable to comply with the GPL, a
* commercial license for this software may be purchased from INSIDE at
* http://www.insidesecure.com/
*
* This program is distributed in WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* http://www.gnu.org/copyleft/gpl.html
*/
/******************************************************************************/
#ifndef _h_OPENSSL_PUBKEY
#define _h_OPENSSL_PUBKEY
/******************************************************************************/
#ifdef USE_OPENSSL_RSA
#include <openssl/rsa.h>
/*
typedef struct {
BIGNUM *n; // public modulus
BIGNUM *e; // public exponent
BIGNUM *d; // private exponent
BIGNUM *p; // secret prime factor
BIGNUM *q; // secret prime factor
BIGNUM *dmp1; // d mod (p-1)
BIGNUM *dmq1; // d mod (q-1)
BIGNUM *iqmp; // q^-1 mod p
// ...
} RSA;
*/
/** @note This type is a pointer, not the actual RSA structure */
typedef RSA* psRsaKey_t;
#define PS_RSA_STATIC_INIT NULL
#endif
/******************************************************************************/
#endif /* _h_OPENSSL_PUBKEY */

862
crypto/pubkey/rsa.c Normal file
View File

@@ -0,0 +1,862 @@
/**
* @file rsa.c
* @version $Format:%h%d$
*
* RSA crypto.
*/
/*
* Copyright (c) 2013-2016 INSIDE Secure Corporation
* Copyright (c) PeerSec Networks, 2002-2011
* All Rights Reserved
*
* The latest version of this code is available at http://www.matrixssl.org
*
* This software is open source; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This General Public License does NOT permit incorporating this software
* into proprietary programs. If you are unable to comply with the GPL, a
* commercial license for this software may be purchased from INSIDE at
* http://www.insidesecure.com/
*
* This program is distributed in WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* http://www.gnu.org/copyleft/gpl.html
*/
/******************************************************************************/
#include "../cryptoApi.h"
/******************************************************************************/
/* TODO - the following functions are not implementation layer specific...
move to a common file?
Matrix-specific starts at #ifdef USE_MATRIX_RSA
*/
#define ASN_OVERHEAD_LEN_RSA_SHA2 19
#define ASN_OVERHEAD_LEN_RSA_SHA1 15
#ifdef USE_MATRIX_RSA
int32_t pubRsaDecryptSignedElement(psPool_t *pool, psRsaKey_t *key,
unsigned char *in, uint16_t inlen,
unsigned char *out, uint16_t outlen,
void *data)
{
unsigned char *c, *front, *end;
uint16_t outlenWithAsn, len, plen;
int32_t oi, rc;
/* The issue here is that the standard RSA decryption routine requires
the user to know the output length (usually just a hash size). With
these "digitally signed elements" there is an algorithm
identifier surrounding the hash so we use the known magic numbers as
additional lengths of the wrapper since it is a defined ASN sequence,
ASN algorithm oid, and ASN octet string */
if (outlen == SHA256_HASH_SIZE) {
outlenWithAsn = SHA256_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2;
} else if (outlen == SHA1_HASH_SIZE) {
outlenWithAsn = SHA1_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA1;
} else if (outlen == SHA384_HASH_SIZE) {
outlenWithAsn = SHA384_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2;
} else if (outlen == SHA512_HASH_SIZE) {
outlenWithAsn = SHA512_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2;
} else {
psTraceIntCrypto("Unsupported decryptSignedElement hash %d\n", outlen);
return PS_FAILURE;
}
front = c = psMalloc(pool, outlenWithAsn);
if (front == NULL) {
return PS_MEM_FAIL;
}
if ((rc = psRsaDecryptPub(pool, key, in, inlen, c, outlenWithAsn, data)) < 0) {
psFree(front, pool);
psTraceCrypto("Couldn't public decrypt signed element\n");
return rc;
}
/* Parse it */
end = c + outlenWithAsn;
/* @note Below we do a typecast to const to avoid a compiler warning,
although it should be fine to pass a non const pointer into an
api declaring it const, since it is just the API declaring the
contents will not be modified within the API. */
if (getAsnSequence((const unsigned char **)&c,
(uint16_t)(end - c), &len) < 0) {
psTraceCrypto("Couldn't parse signed element sequence\n");
psFree(front, pool);
return PS_FAILURE;
}
if (getAsnAlgorithmIdentifier((const unsigned char **)&c,
(uint16_t)(end - c), &oi, &plen) < 0) {
psTraceCrypto("Couldn't parse signed element octet string\n");
psFree(front, pool);
return PS_FAILURE;
}
if (oi == OID_SHA256_ALG) {
psAssert(outlen == SHA256_HASH_SIZE);
} else if (oi == OID_SHA1_ALG) {
psAssert(outlen == SHA1_HASH_SIZE);
} else if (oi == OID_SHA384_ALG) {
psAssert(outlen == SHA384_HASH_SIZE);
} else {
psAssert(outlen == SHA512_HASH_SIZE);
}
/* Note the last test here requires the buffer to be exactly outlen bytes */
if ((end - c) < 1 || (*c++ != ASN_OCTET_STRING) ||
getAsnLength((const unsigned char **)&c, (uint16_t)(end - c), &len) < 0 ||
(uint32_t)(end - c) != outlen) {
psTraceCrypto("Couldn't parse signed element octet string\n");
psFree(front, pool);
return PS_FAILURE;
}
/* Will finally be sitting at the hash now */
memcpy(out, c, outlen);
psFree(front, pool);
return PS_SUCCESS;
}
/*
ASN wrappers around standard hash signatures. These versions sign
a BER wrapped hash. Here are the well-defined wrappers:
*/
static const unsigned char asn256dsWrap[] = {0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60,
0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
#ifdef USE_SHA384
static const unsigned char asn384dsWrap[] = {0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60,
0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
#endif
static const unsigned char asn1dsWrap[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B,
0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14};
int32_t privRsaEncryptSignedElement(psPool_t *pool, psRsaKey_t *key,
const unsigned char *in, uint16_t inlen,
unsigned char *out, uint16_t outlen,
void *data)
{
unsigned char c[MAX_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2];
uint32_t inlenWithAsn;
switch (inlen) {
#ifdef USE_SHA256
case SHA256_HASH_SIZE:
inlenWithAsn = inlen + ASN_OVERHEAD_LEN_RSA_SHA2;
memcpy(c, asn256dsWrap, ASN_OVERHEAD_LEN_RSA_SHA2);
memcpy(c + ASN_OVERHEAD_LEN_RSA_SHA2, in, inlen);
break;
#endif
#ifdef USE_SHA1
case SHA1_HASH_SIZE:
inlenWithAsn = inlen + ASN_OVERHEAD_LEN_RSA_SHA1;
memcpy(c, asn1dsWrap, ASN_OVERHEAD_LEN_RSA_SHA1);
memcpy(c + ASN_OVERHEAD_LEN_RSA_SHA1, in, inlen);
break;
#endif
#ifdef USE_SHA384
case SHA384_HASH_SIZE:
inlenWithAsn = inlen + ASN_OVERHEAD_LEN_RSA_SHA2;
memcpy(c, asn384dsWrap, ASN_OVERHEAD_LEN_RSA_SHA2);
memcpy(c + ASN_OVERHEAD_LEN_RSA_SHA2, in, inlen);
break;
#endif
default:
return PS_UNSUPPORTED_FAIL;
}
if (psRsaEncryptPriv(pool, key, c, inlenWithAsn,
out, outlen, data) < 0) {
psTraceCrypto("privRsaEncryptSignedElement failed\n");
memzero_s(c, sizeof(c));
return PS_PLATFORM_FAIL;
}
memzero_s(c, sizeof(c));
return PS_SUCCESS;
}
/******************************************************************************/
/**
Initialize an allocated RSA key.
@note that in this case, a psRsaKey_t is a structure type.
This means that the caller must have statically or dynamically allocated
the structure before calling this Api.
TODO, may not be necessary, since crypt apis also take pool.
@param[in] pool The pool to use to allocate any temporary working memory
beyond what is provided in the 'key' structure.
@param[in,out] key A pointer to an allocated (statically or dynamically)
key structure to be initalized as a blank RSA keypair.
*/
int32_t psRsaInitKey(psPool_t *pool, psRsaKey_t *key)
{
if (!key) {
return PS_MEM_FAIL;
}
memset(key, 0x0, sizeof(psRsaKey_t));
key->pool = pool;
return PS_SUCCESS;
}
/*
Zero an RSA key. The caller is responsible for freeing 'key' if it is
allocated (or not if it is static, or stack based).
*/
void psRsaClearKey(psRsaKey_t *key)
{
pstm_clear(&(key->N));
pstm_clear(&(key->e));
pstm_clear(&(key->d));
pstm_clear(&(key->p));
pstm_clear(&(key->q));
pstm_clear(&(key->dP));
pstm_clear(&(key->dQ));
pstm_clear(&(key->qP));
key->size = 0;
key->optimized = 0;
key->pool = NULL;
}
/* 'to' key digits are allocated here */
int32_t psRsaCopyKey(psRsaKey_t *to, const psRsaKey_t *from)
{
int32_t err = 0;
if ((err = pstm_init_copy(from->pool, &to->N, &from->N, 0)) != PSTM_OKAY) {
goto error; }
if ((err = pstm_init_copy(from->pool, &to->e, &from->e, 0)) != PSTM_OKAY) {
goto error; }
if ((err = pstm_init_copy(from->pool, &to->d, &from->d, 0)) != PSTM_OKAY) {
goto error; }
if ((err = pstm_init_copy(from->pool, &to->p, &from->p, 0)) != PSTM_OKAY) {
goto error; }
if ((err = pstm_init_copy(from->pool, &to->q, &from->q, 0)) != PSTM_OKAY) {
goto error; }
if ((err = pstm_init_copy(from->pool, &to->dP, &from->dP, 0)) != PSTM_OKAY){
goto error; }
if ((err = pstm_init_copy(from->pool, &to->dQ, &from->dQ, 0)) != PSTM_OKAY){
goto error; }
if ((err = pstm_init_copy(from->pool, &to->qP, &from->qP, 0)) != PSTM_OKAY){
goto error; }
to->size = from->size;
to->optimized = from->optimized;
to->pool = from->pool;
error:
if (err < 0) {
psRsaClearKey(to);
}
return err;
}
#endif /* USE_MATRIX_RSA */
#ifdef USE_RSA
/******************************************************************************/
/**
Get the size in bytes of the RSA public exponent.
Eg. 128 for 1024 bit RSA keys, 256 for 2048 and 512 for 4096 bit keys.
@param[in] key RSA key
@return Number of bytes of public exponent.
*/
uint16_t psRsaSize(const psRsaKey_t *key)
{
return key->size;
}
/******************************************************************************/
/**
Compare if the public modulus and exponent is the same between two keys.
@return < 0 on failure, >= 0 on success.
*/
int32_t psRsaCmpPubKey(const psRsaKey_t *k1, const psRsaKey_t *k2)
{
if ((pstm_cmp(&k1->N, &k2->N) == PSTM_EQ) &&
(pstm_cmp(&k1->e, &k2->e) == PSTM_EQ)) {
return PS_SUCCESS;
}
return PS_FAIL;
}
#ifdef OLD
/******************************************************************************/
/*
*/
static int32_t getBig(psPool_t *pool, const unsigned char **pp, uint16_t len,
pstm_int *big)
{
const unsigned char *p = *pp;
uint16_t vlen;
if (len < 1 || *(p++) != ASN_INTEGER ||
getAsnLength(&p, len - 1, &vlen) < 0 || (len - 1) < vlen) {
return PS_PARSE_FAIL;
}
/* Make a smart size since we know the length */
if (pstm_init_for_read_unsigned_bin(pool, big, vlen) != PSTM_OKAY) {
return PS_MEM_FAIL;
}
if (pstm_read_unsigned_bin(big, p, vlen) != 0) {
pstm_clear(big);
psTraceCrypto("ASN getBig failed\n");
return PS_PARSE_FAIL;
}
*pp = p + vlen;
return PS_SUCCESS;
}
#endif
/******************************************************************************/
/**
Parse an RSA public key from an ASN.1 byte stream.
@return < 0 on error, >= 0 on success.
*/
int32_t psRsaParseAsnPubKey(psPool_t *pool,
const unsigned char **pp, uint16_t len,
psRsaKey_t *key, unsigned char sha1KeyHash[SHA1_HASH_SIZE])
{
#ifdef USE_SHA1
psDigestContext_t dc;
#endif
const unsigned char *p = *pp;
uint16_t keylen, seqlen;
if (len < 1 || (*(p++) != ASN_BIT_STRING) ||
getAsnLength(&p, len - 1, &keylen) < 0 ||
(len - 1) < keylen) {
goto L_FAIL;
}
if (*p++ != 0) {
goto L_FAIL;
}
#ifdef USE_SHA1
/* A public key hash is used in PKI tools (OCSP, Trusted CA indication).
Standard RSA form - SHA-1 hash of the value of the BIT STRING
subjectPublicKey [excluding the tag, length, and number of unused
bits] */
psSha1Init(&dc.sha1);
psSha1Update(&dc.sha1, p, keylen - 1);
psSha1Final(&dc.sha1, sha1KeyHash);
#endif
if (getAsnSequence(&p, keylen, &seqlen) < 0 ||
pstm_read_asn(pool, &p, seqlen, &key->N) < 0 ||
pstm_read_asn(pool, &p, seqlen, &key->e) < 0) {
goto L_FAIL;
}
key->size = pstm_unsigned_bin_size(&key->N);
key->pool = pool;
#ifdef USE_TILERA_RSA
#ifdef USE_RSA_PUBLIC_NONBLOCKING
key->nonBlock = 1;
#else
key->nonBlock = 0;
#endif
#endif
*pp = p;
return PS_SUCCESS;
L_FAIL:
psTraceIntCrypto("psRsaReadAsnPubKey error on byte %d\n", p - *pp);
return PS_PARSE_FAIL;
}
#ifdef USE_PRIVATE_KEY_PARSING
/******************************************************************************/
/**
Parse a a private key structure in DER formatted ASN.1
Per ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
RSAPrivateKey ::= SEQUENCE {
version Version,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
}
Version ::= INTEGER { two-prime(0), multi(1) }
(CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
Which should look something like this in hex (pipe character
is used as a delimiter):
ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc
30 Tag in binary: 00|1|10000 -> UNIVERSAL | CONSTRUCTED | SEQUENCE (16)
82 Length in binary: 1 | 0000010 -> LONG LENGTH | LENGTH BYTES (2)
04 A4 Length Bytes (1188)
02 Tag in binary: 00|0|00010 -> UNIVERSAL | PRIMITIVE | INTEGER (2)
01 Length in binary: 0|0000001 -> SHORT LENGTH | LENGTH (1)
00 INTEGER value (0) - RSAPrivateKey.version
02 Tag in binary: 00|0|00010 -> UNIVERSAL | PRIMITIVE | INTEGER (2)
82 Length in binary: 1 | 0000010 -> LONG LENGTH | LENGTH BYTES (2)
01 01 Length Bytes (257)
[] 257 Bytes of data - RSAPrivateKey.modulus (2048 bit key)
02 Tag in binary: 00|0|00010 -> UNIVERSAL | PRIMITIVE | INTEGER (2)
03 Length in binary: 0|0000011 -> SHORT LENGTH | LENGTH (3)
01 00 01 INTEGER value (65537) - RSAPrivateKey.publicExponent
...
OtherPrimeInfos is not supported in this routine, and an error will be
returned if they are present
@return < 0 on error, >= 0 on success.
*/
int32_t psRsaParsePkcs1PrivKey(psPool_t *pool,
const unsigned char *p, uint16_t size,
psRsaKey_t *key)
{
const unsigned char *end, *seq;
int32_t version;
uint16_t seqlen;
if (psRsaInitKey(pool, key) < 0) {
return PS_MEM_FAIL;
}
end = p + size;
if (getAsnSequence(&p, size, &seqlen) < 0) {
psRsaClearKey(key);
return PS_PARSE_FAIL;
}
seq = p;
if (getAsnInteger(&p, (uint16_t)(end - p), &version) < 0 || version != 0 ||
pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->N)) < 0 ||
pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->e)) < 0 ||
pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->d)) < 0 ||
pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->p)) < 0 ||
pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->q)) < 0 ||
pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->dP)) < 0 ||
pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->dQ)) < 0 ||
pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->qP)) < 0 ||
(uint16_t)(p - seq) != seqlen) {
psTraceCrypto("ASN RSA private key extract parse error\n");
psRsaClearKey(key);
return PS_PARSE_FAIL;
}
#ifdef USE_TILERA_RSA
/* EIP-54 usage limitation that some operands must be larger than others.
If you are seeing RSA unpad failures after decryption, try toggling
this swap. It does seem to work 100% of the time by either performing
or not performing this swap. */
/* EIP-24 requires dP > dQ. Swap and recalc qP */
if (pstm_cmp_mag(&key->p, &key->q) == PSTM_LT) {
pstm_exch(&key->dP, &key->dQ);
pstm_exch(&key->p, &key->q);
pstm_zero(&key->qP);
pstm_invmod(pool, &key->q, &key->p, &key->qP);
}
#ifdef USE_RSA_PRIVATE_NONBLOCKING
key->nonBlock = 1;
#else
key->nonBlock = 0;
#endif
#endif /* USE_TILERA_RSA */
/*
If we made it here, the key is ready for optimized decryption
Set the key length of the key
*/
key->optimized = 1;
key->size = pstm_unsigned_bin_size(&key->N);
/* Should be at the end */
if (end != p) {
/* If this stream came from an encrypted file, there could be
padding bytes on the end */
seqlen = (uint16_t)(end - p);
while (p < end) {
if (*p != seqlen) {
psTraceCrypto("Problem at end of private key parse\n");
}
p++;
}
}
return PS_SUCCESS;
}
#endif /* USE_PRIVATE_KEY_PARSING */
#endif /* USE_RSA */
#ifdef USE_MATRIX_RSA
/******************************************************************************/
/**
Primary RSA crypto routine, with either public or private key.
@param[in] pool Pool to use for temporary memory allocation for this op.
@param[in] key RSA key to use for this operation.
@param[in] in Pointer to allocated buffer to encrypt.
@param[in] inlen Number of bytes pointed to by 'in' to encrypt.
@param[out] out Pointer to allocated buffer to store encrypted data.
@param[out] outlen Number of bytes written to 'out' buffer.
@param[in] type PS_PRIVKEY or PS_PUBKEY.
@param[in] data TODO Hardware context.
@return 0 on success, < 0 on failure.
@note 'out' and 'in' can be equal for in-situ operation.
*/
int32_t psRsaCrypt(psPool_t *pool, psRsaKey_t *key,
const unsigned char *in, uint16_t inlen,
unsigned char *out, uint16_t *outlen,
uint8_t type, void *data)
{
pstm_int tmp, tmpa, tmpb;
int32_t res;
uint32_t x;
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 == PS_PRIVKEY) {
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 == PS_PUBKEY) {
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 == PS_PRIVKEY && key->optimized) {
pstm_clear_multi(&tmpa, &tmpb, NULL, NULL, NULL, NULL, NULL, NULL);
}
pstm_clear(&tmp);
return res;
}
/******************************************************************************/
/**
RSA private encryption. This is used by a private key holder to sign
data that can be verified by psRsaDecryptPub().
@param[in] pool Pool to use for temporary memory allocation for this op.
@param[in] key RSA key to use for this operation.
@param[in] in Pointer to allocated buffer to encrypt.
@param[in] inlen Number of bytes pointed to by 'in' to encrypt.
@param[out] out Pointer to allocated buffer to store encrypted data.
@param[out] outlen Number of bytes written to 'out' buffer.
@param[in] data TODO Hardware context.
@return 0 on success, < 0 on failure.
*/
int32_t psRsaEncryptPriv(psPool_t *pool, psRsaKey_t *key,
const unsigned char *in, uint16_t inlen,
unsigned char *out, uint16_t outlen,
void *data)
{
unsigned char *verify = NULL;
unsigned char *tmpout = NULL;
int32_t err;
uint16_t size, olen;
size = key->size;
if (outlen < size) {
psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPriv\n");
return PS_ARG_FAIL;
}
olen = outlen; /* Save in case we zero 'out' later */
if ((err = pkcs1Pad(in, inlen, out, size, PS_PUBKEY, data)) < PS_SUCCESS){
psTraceCrypto("Error padding psRsaEncryptPriv. Likely data too long\n");
return err;
}
if ((err = psRsaCrypt(pool, key, out, size, out, &outlen,
PS_PRIVKEY, data)) < PS_SUCCESS) {
psTraceCrypto("Error performing psRsaEncryptPriv\n");
return err;
}
if (outlen != size) {
goto L_FAIL;
}
/**
@security Verify the signature we just made before it is used
by the caller. If the signature is invalid for some reason
(hardware or software error or memory overrun), it can
leak information on the private key.
*/
if ((verify = psMalloc(pool, inlen)) == NULL) {
goto L_FAIL;
}
/* psRsaDecryptPub overwrites the input, so duplicate it here */
if ((tmpout = psMalloc(pool, outlen)) == NULL) {
goto L_FAIL;
}
memcpy(tmpout, out, outlen);
if (psRsaDecryptPub(pool, key,
tmpout, outlen, verify, inlen, data) < 0) {
goto L_FAIL;
}
if (memcmpct(in, verify, inlen) != 0) {
goto L_FAIL;
}
memzero_s(verify, inlen);
psFree(verify, pool);
memzero_s(tmpout, outlen);
psFree(tmpout, pool);
return PS_SUCCESS;
L_FAIL:
memzero_s(out, olen); /* Clear, to ensure bad result isn't used */
if (tmpout) {
memzero_s(tmpout, outlen);
psFree(tmpout, pool);
}
if (verify) {
memzero_s(verify, inlen);
psFree(verify, pool);
}
psTraceCrypto("Signature mismatch in psRsaEncryptPriv\n");
return PS_FAIL;
}
/******************************************************************************/
/**
RSA public encryption. This is used by a public key holder to do
key exchange with the private key holder, which can access the key using
psRsaDecryptPriv().
@param[in] pool Pool to use for temporary memory allocation for this op.
@param[in] key RSA key to use for this operation.
@param[in] in Pointer to allocated buffer to encrypt.
@param[in] inlen Number of bytes pointed to by 'in' to encrypt.
@param[out] out Pointer to allocated buffer to store encrypted data.
@param[in] expected output length
@param[in] data TODO Hardware context.
@return 0 on success, < 0 on failure.
*/
int32_t psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key,
const unsigned char *in, uint16_t inlen,
unsigned char *out, uint16_t outlen,
void *data)
{
int32_t err;
uint16_t size;
size = key->size;
if (outlen < size) {
psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub\n");
return PS_ARG_FAIL;
}
if ((err = pkcs1Pad(in, inlen, out, size, PS_PRIVKEY, data))
< PS_SUCCESS) {
psTraceCrypto("Error padding psRsaEncryptPub. Likely data too long\n");
return err;
}
if ((err = psRsaCrypt(pool, key, out, size, out, &outlen,
PS_PUBKEY, data)) < PS_SUCCESS) {
psTraceCrypto("Error performing psRsaEncryptPub\n");
return err;
}
if (outlen != size) {
psTraceCrypto("Encrypted size error in psRsaEncryptPub\n");
return PS_FAILURE;
}
return PS_SUCCESS;
}
/******************************************************************************/
/**
RSA private decryption. This is used by a private key holder to decrypt
a key exchange with the public key holder, which encodes the key using
psRsaEncryptPub().
@param[in] pool Pool to use for temporary memory allocation for this op.
@param[in] key RSA key to use for this operation.
@param[in,out] in Pointer to allocated buffer to encrypt.
@param[in] inlen Number of bytes pointed to by 'in' to encrypt.
@param[out] out Pointer to allocated buffer to store encrypted data.
@param[out] outlen Number of bytes written to 'out' buffer.
@param[in] data TODO Hardware context.
@return 0 on success, < 0 on failure.
TODO -fix
@note this function writes over the 'in' buffer
*/
int32_t psRsaDecryptPriv(psPool_t *pool, psRsaKey_t *key,
unsigned char *in, uint16_t inlen,
unsigned char *out, uint16_t outlen,
void *data)
{
int32_t err;
uint16_t ptLen;
if (inlen != key->size) {
psTraceCrypto("Error on bad inlen parameter to psRsaDecryptPriv\n");
return PS_ARG_FAIL;
}
ptLen = inlen;
if ((err = psRsaCrypt(pool, key, in, inlen, in, &ptLen,
PS_PRIVKEY, data)) < PS_SUCCESS) {
psTraceCrypto("Error performing psRsaDecryptPriv\n");
return err;
}
if (ptLen != inlen) {
psTraceCrypto("Decrypted size error in psRsaDecryptPriv\n");
return PS_FAILURE;
}
err = pkcs1Unpad(in, inlen, out, outlen, PS_PRIVKEY);
memset(in, 0x0, inlen);
return err;
}
/******************************************************************************/
/**
RSA public decryption. This is used by a public key holder to verify
a signature by the private key holder, who signs using psRsaEncryptPriv().
@param[in] pool Pool to use for temporary memory allocation for this op.
@param[in] key RSA key to use for this operation.
@param[in,out] in Pointer to allocated buffer to encrypt.
@param[in] inlen Number of bytes pointed to by 'in' to encrypt.
@param[out] out Pointer to allocated buffer to store encrypted data.
@param[in] outlen length of expected output.
@param[in] data TODO Hardware context.
@return 0 on success, < 0 on failure.
TODO -fix
@note this function writes over the 'in' buffer
*/
int32_t psRsaDecryptPub(psPool_t *pool, psRsaKey_t *key,
unsigned char *in, uint16_t inlen,
unsigned char *out, uint16_t outlen,
void *data)
{
int32_t err;
uint16_t ptLen;
if (inlen != key->size) {
psTraceCrypto("Error on bad inlen parameter to psRsaDecryptPub\n");
return PS_ARG_FAIL;
}
ptLen = inlen;
if ((err = psRsaCrypt(pool, key, in, inlen, in, &ptLen,
PS_PUBKEY, data)) < PS_SUCCESS) {
psTraceCrypto("Error performing psRsaDecryptPub\n");
return err;
}
if (ptLen != inlen) {
psTraceIntCrypto("Decrypted size error in psRsaDecryptPub %d\n", ptLen);
return PS_FAILURE;
}
if ((err = pkcs1Unpad(in, inlen, out, outlen, PS_PUBKEY)) < 0) {
return err;
}
return PS_SUCCESS;
}
#endif /* USE_MATRIX_RSA */
/******************************************************************************/

345
crypto/pubkey/rsa_openssl.c Normal file
View File

@@ -0,0 +1,345 @@
/**
* @file rsa_openssl.c
* @version $Format:%h%d$
*
* RSA compatibility layer between MatrixSSL and OpenSSL.
*/
/*
* Copyright (c) 2013-2016 INSIDE Secure Corporation
* Copyright (c) PeerSec Networks, 2002-2011
* All Rights Reserved
*
* The latest version of this code is available at http://www.matrixssl.org
*
* This software is open source; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This General Public License does NOT permit incorporating this software
* into proprietary programs. If you are unable to comply with the GPL, a
* commercial license for this software may be purchased from INSIDE at
* http://www.insidesecure.com/
*
* This program is distributed in WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* http://www.gnu.org/copyleft/gpl.html
*/
/******************************************************************************/
#include "../cryptoApi.h"
#ifdef USE_OPENSSL_RSA
#include "openssl/bn.h"
/**
@note It bears mention that the DER parsing functions
are defined in this header via macro:
DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPublicKey)
DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPrivateKey)
They are implemented in openssl/crypto/rsa/rsa_asn1.c:
ASN1_SEQUENCE_cb(RSAPrivateKey, rsa_cb) = {
ASN1_SIMPLE(RSA, version, LONG),
ASN1_SIMPLE(RSA, n, BIGNUM),
ASN1_SIMPLE(RSA, e, BIGNUM),
ASN1_SIMPLE(RSA, d, BIGNUM),
ASN1_SIMPLE(RSA, p, BIGNUM),
ASN1_SIMPLE(RSA, q, BIGNUM),
ASN1_SIMPLE(RSA, dmp1, BIGNUM),
ASN1_SIMPLE(RSA, dmq1, BIGNUM),
ASN1_SIMPLE(RSA, iqmp, BIGNUM)
} ASN1_SEQUENCE_END_cb(RSA, RSAPrivateKey)
ASN1_SEQUENCE_cb(RSAPublicKey, rsa_cb) = {
ASN1_SIMPLE(RSA, n, BIGNUM),
ASN1_SIMPLE(RSA, e, BIGNUM),
} ASN1_SEQUENCE_END_cb(RSA, RSAPublicKey)
In turn, the asn BIGNUM creation is in crypto/asn1/x_bignum.c
*/
#include "openssl/rsa.h"
/**
Note that in this case psRsaKey_t is a pointer type, so 'key' is
effectively a double pointer. We just set it to NULL for now, the actual
key will be allocated by the parse functions below.
@param[in] pool Unused in this implementation.
@param[in,out] key A pointer to an allocated (statically or dynamically)
psRsaKey_t, which in this case is just a pointer to an RSA structure.
*/
int32_t psRsaInitKey(psPool_t *pool, psRsaKey_t *key)
{
*key = NULL;
return PS_SUCCESS;
}
/******************************************************************************/
/**
RSA_free() frees and zeroes the RSA structure and associated BIGNUM values.
*/
void psRsaClearKey(psRsaKey_t *key)
{
if (key && *key) {
RSA_free(*key);
*key = NULL;
}
}
/******************************************************************************/
/**
*/
int32_t psRsaCopyKey(psRsaKey_t *to, const psRsaKey_t *from)
{
RSA *t = *to;
RSA *f = *from;
if (!from || !f || !to) {
return PS_ARG_FAIL;
}
/* If to already contained a key, free it */
if (t) {
RSA_free(t);
}
/* Allocate a new key */
if ((t = RSA_new()) == NULL) {
return PS_MEM_FAIL;
}
/* Duplicate the parts that must always be present (n, e) */
if ((t->n = BN_dup(f->n)) == NULL) {
RSA_free(t);
return PS_FAIL;
}
if ((t->e = BN_dup(f->e)) == NULL) {
RSA_free(t);
return PS_FAIL;
}
/* Duplicate the private/optimized parts. Ok if they are NULL */
t->d = BN_dup(f->d);
t->p = BN_dup(f->p);
t->q = BN_dup(f->q);
t->dmp1 = BN_dup(f->dmp1);
t->dmq1 = BN_dup(f->dmq1);
t->iqmp = BN_dup(f->iqmp);
*to = t;
return PS_SUCCESS;
}
/******************************************************************************/
/**
Returns the size of the RSA public modulus in bytes.
@return 0 on uninitalized key, or >= for valid key
(eg. 128 for 1024 bit key, etc)
*/
uint16_t psRsaSize(const psRsaKey_t *key)
{
if (key && *key) {
return RSA_size(*key);
}
return 0;
}
/******************************************************************************/
int32_t psRsaCmpPubKey(const psRsaKey_t *k1, const psRsaKey_t *k2)
{
/* BN_cmp() returns -1 if a < b, 0 if a == b and 1 if a > b. */
if ((BN_cmp((*k1)->n, (*k2)->n) == 0) &&
(BN_cmp((*k1)->e, (*k2)->e) == 0)) {
return PS_SUCCESS;
}
return PS_FAIL;
}
#ifndef USE_D2I
/******************************************************************************/
/**
Convert big endian binary data to a native big number type.
BN_bin2bn() converts the positive integer in big-endian form of length len
at s into a BIGNUM and places it in ret.
If ret is NULL, a new BIGNUM is created.
BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
*/
static int32_t getBig(const unsigned char **pp, uint16_t len, BIGNUM **big)
{
const unsigned char *p = *pp;
uint16_t vlen;
BIGNUM *bn;
if (len < 1 || *(p++) != ASN_INTEGER ||
getAsnLength(&p, len - 1, &vlen) < 0 || (len - 1) < vlen) {
return PS_PARSE_FAIL;
}
if ((bn = BN_bin2bn(p, vlen, NULL)) == NULL) {
return PS_MEM_FAIL;
}
/* BN_print_fp(stdout, bn); */
*big = bn;
*pp = p + vlen;
return PS_SUCCESS;
}
#endif
/******************************************************************************/
/*
Parse DER encoded asn.1 RSA public key out of a certificate stream.
We reach here with 'pp' pointing to the byte after the algorithm identifier.
*/
int32_t psRsaParseAsnPubKey(psPool_t *pool,
const unsigned char **pp, uint16_t len,
psRsaKey_t *key, unsigned char sha1KeyHash[SHA1_HASH_SIZE])
{
#ifdef USE_SHA1
psDigestContext_t dc;
#endif
const unsigned char *p = *pp;
RSA *rsa;
uint16_t keylen;
#ifndef USE_D2I
uint16_t seqlen;
#endif
if (len < 1 || (*(p++) != ASN_BIT_STRING) ||
getAsnLength(&p, len - 1, &keylen)) {
goto L_FAIL;
}
/* ignored bits field should be zero */
if (*p++ != 0) {
goto L_FAIL;
}
keylen--;
#ifdef USE_SHA1
/* A public key hash is used in PKI tools (OCSP, Trusted CA indication).
Standard RSA form - SHA-1 hash of the value of the BIT STRING
subjectPublicKey [excluding the tag, length, and number of unused
bits] */
psSha1Init(&dc.sha1);
psSha1Update(&dc.sha1, p, keylen);
psSha1Final(&dc.sha1, sha1KeyHash);
#endif
#ifdef USE_D2I
/* OpenSSL expects to parse after the ignored bits field */
if ((rsa = d2i_RSAPublicKey(NULL, &p, keylen)) == NULL) {
goto L_FAIL;
}
#else
/* We can manually create the structures as OpenSSL would */
rsa = RSA_new();
if (getAsnSequence(&p, keylen, &seqlen) < 0 ||
getBig(&p, seqlen, &rsa->n) < 0 ||
getBig(&p, seqlen, &rsa->e) < 0) {
RSA_free(rsa);
goto L_FAIL;
}
#endif
/* RSA_print_fp(stdout, rsa, 0); */
*pp = p;
*key = rsa;
return PS_SUCCESS;
L_FAIL:
psTraceIntCrypto("psRsaParseAsnPubKey error on byte %d\n", p - *pp);
return PS_PARSE_FAIL;
}
#ifdef USE_PRIVATE_KEY_PARSING
/******************************************************************************/
/**
Parse an RSA private key from a PKCS#1 byte stream.
@see ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
*/
int32_t psRsaParsePkcs1PrivKey(psPool_t *pool,
const unsigned char *p, uint16_t size,
psRsaKey_t *key)
{
RSA *rsa;
#ifndef USE_D2I
const unsigned char *end, *seq;
int32_t version;
uint16_t seqlen;
#endif
#ifdef USE_D2I
if ((rsa = d2i_RSAPrivateKey(NULL, &p, size)) == NULL) {
return PS_PARSE_FAIL;
}
#else
if ((rsa = RSA_new()) == NULL) {
return PS_MEM_FAIL;
}
end = p + size;
if (getAsnSequence(&p, size, &seqlen) < 0) {
RSA_free(rsa);
goto L_FAIL;
}
seq = p;
if (getAsnInteger(&p, (uint16_t)(end - p), &version) < 0 || version != 0 ||
getBig(&p, (uint16_t)(end - p), &rsa->n) < 0 ||
getBig(&p, (uint16_t)(end - p), &rsa->e) < 0 ||
getBig(&p, (uint16_t)(end - p), &rsa->d) < 0 ||
getBig(&p, (uint16_t)(end - p), &rsa->p) < 0 ||
getBig(&p, (uint16_t)(end - p), &rsa->q) < 0 ||
getBig(&p, (uint16_t)(end - p), &rsa->dmp1) < 0 ||
getBig(&p, (uint16_t)(end - p), &rsa->dmq1) < 0 ||
getBig(&p, (uint16_t)(end - p), &rsa->iqmp) < 0 ||
(uint16_t)(p - seq) != seqlen) {
RSA_free(rsa);
goto L_FAIL;
}
rsa->version = version;
#endif
/* RSA_print_fp(stdout, rsa, 0); */
*key = rsa;
return PS_SUCCESS;
L_FAIL:
psTraceIntCrypto("psRsaParsePkcs1PrivKey error on byte %d\n", p - (end - size));
return PS_PARSE_FAIL;
}
#endif /* USE_PRIVATE_KEY_PARSING */
/******************************************************************************/
int32_t psRsaEncryptPriv(psPool_t *pool, psRsaKey_t *key,
const unsigned char *in, uint16_t inlen,
unsigned char *out, uint16_t outlen,
void *data)
{
return RSA_private_encrypt(inlen, in, out, *key, RSA_PKCS1_PADDING);
}
int32_t psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key,
const unsigned char *in, uint16_t inlen,
unsigned char *out, uint16_t outlen,
void *data)
{
return RSA_public_encrypt(inlen, in, out, *key, RSA_PKCS1_PADDING);
}
int32_t psRsaDecryptPriv(psPool_t *pool, psRsaKey_t *key,
unsigned char *in, uint16_t inlen,
unsigned char *out, uint16_t outlen,
void *data)
{
return RSA_private_decrypt(inlen, in, out, *key, RSA_PKCS1_PADDING);
}
int32_t psRsaDecryptPub(psPool_t *pool, psRsaKey_t *key,
unsigned char *in, uint16_t inlen,
unsigned char *out, uint16_t outlen,
void *data)
{
return RSA_public_decrypt(inlen, in, out, *key, RSA_PKCS1_PADDING);
}
#endif /* USE_OPENSSL_RSA */
/******************************************************************************/