MatrixSSL 3.8.3 Open
This commit is contained in:
447
crypto/pubkey/dh.c
Normal file
447
crypto/pubkey/dh.c
Normal 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), ¶ms->p) < 0) {
|
||||
goto L_ERR;
|
||||
}
|
||||
params->size = pstm_unsigned_bin_size(¶ms->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), ¶ms->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(¶ms->g);
|
||||
pstm_clear(¶ms->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(¶ms->g);
|
||||
pstm_clear(¶ms->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(¶ms->p);
|
||||
gl = pstm_unsigned_bin_size(¶ms->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, ¶ms->p, p) < 0 ||
|
||||
pstm_to_unsigned_bin(pool, ¶ms->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
2695
crypto/pubkey/ecc.c
Normal file
File diff suppressed because it is too large
Load Diff
184
crypto/pubkey/pubkey.c
Normal file
184
crypto/pubkey/pubkey.c
Normal 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
208
crypto/pubkey/pubkey.h
Normal 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 */
|
||||
|
||||
117
crypto/pubkey/pubkey_matrix.h
Normal file
117
crypto/pubkey/pubkey_matrix.h
Normal 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 */
|
||||
|
||||
66
crypto/pubkey/pubkey_openssl.h
Normal file
66
crypto/pubkey/pubkey_openssl.h
Normal 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
862
crypto/pubkey/rsa.c
Normal 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
345
crypto/pubkey/rsa_openssl.c
Normal 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 */
|
||||
/******************************************************************************/
|
||||
|
||||
Reference in New Issue
Block a user