add cert gen for ecc certs

This commit is contained in:
toddouska 2013-11-14 20:34:39 -08:00
parent a7bcca84c3
commit d91e8ab38e
5 changed files with 196 additions and 36 deletions

View File

@ -1434,7 +1434,7 @@ static int GetKey(DecodedCert* cert)
if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
return ASN_PARSE_E;
if (GetAlgoId(cert->source, &cert->srcIdx, &cert->keyOID, cert->maxIdx) < 0)
return ASN_PARSE_E;
@ -2128,10 +2128,14 @@ int DecodeToKey(DecodedCert* cert, int verify)
if ( (ret = GetCertHeader(cert)) < 0)
return ret;
CYASSL_MSG("Got Cert Header");
if ( (ret = GetAlgoId(cert->source, &cert->srcIdx, &cert->signatureOID,
cert->maxIdx)) < 0)
return ret;
CYASSL_MSG("Got Algo ID");
if ( (ret = GetName(cert, ISSUER)) < 0)
return ret;
@ -2141,9 +2145,13 @@ int DecodeToKey(DecodedCert* cert, int verify)
if ( (ret = GetName(cert, SUBJECT)) < 0)
return ret;
CYASSL_MSG("Got Subject Name");
if ( (ret = GetKey(cert)) < 0)
return ret;
CYASSL_MSG("Got Key");
if (badDate != 0)
return badDate;
@ -2223,7 +2231,80 @@ static word32 SetSequence(word32 len, byte* output)
}
static word32 SetAlgoID(int algoOID, byte* output, int type)
#if defined(HAVE_ECC) && defined(CYASSL_CERT_GEN)
static word32 SetCurve(ecc_key* key, byte* output)
{
/* curve types */
static const byte ECC_192v1_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
0x03, 0x01, 0x01};
static const byte ECC_256v1_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
0x03, 0x01, 0x07};
static const byte ECC_160r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
0x02};
static const byte ECC_224r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
0x21};
static const byte ECC_384r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
0x22};
static const byte ECC_521r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
0x23};
int oidSz = 0;
int idx = 0;
int lenSz = 0;
const byte* oid = 0;
output[0] = ASN_OBJECT_ID;
idx++;
switch (key->dp->size) {
case 20:
oidSz = sizeof(ECC_160r1_AlgoID);
oid = ECC_160r1_AlgoID;
break;
case 24:
oidSz = sizeof(ECC_192v1_AlgoID);
oid = ECC_192v1_AlgoID;
break;
case 28:
oidSz = sizeof(ECC_224r1_AlgoID);
oid = ECC_224r1_AlgoID;
break;
case 32:
oidSz = sizeof(ECC_256v1_AlgoID);
oid = ECC_256v1_AlgoID;
break;
case 48:
oidSz = sizeof(ECC_384r1_AlgoID);
oid = ECC_384r1_AlgoID;
break;
case 66:
oidSz = sizeof(ECC_521r1_AlgoID);
oid = ECC_521r1_AlgoID;
break;
default:
return ASN_UNKNOWN_OID_E;
}
lenSz = SetLength(oidSz, output+idx);
idx += lenSz;
XMEMCPY(output+idx, oid, oidSz);
idx += oidSz;
return idx;
}
#endif /* HAVE_ECC && CYASSL_CERT_GEN */
static word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
{
/* adding TAG_NULL and 0 to end */
@ -2274,11 +2355,14 @@ static word32 SetAlgoID(int algoOID, byte* output, int type)
#endif /* NO_RSA */
#ifdef HAVE_ECC
static const byte ECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
0x04, 0x02, 0x05, 0x00};
/* ECC keyType */
/* no tags, so set tagSz smaller later */
static const byte ECC_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
0x02, 0x01};
#endif /* HAVE_ECC */
int algoSz = 0;
int tagSz = 2; /* tag null and terminator */
word32 idSz, seqSz;
const byte* algoName = 0;
byte ID_Length[MAX_LENGTH_SZ];
@ -2385,8 +2469,9 @@ static word32 SetAlgoID(int algoOID, byte* output, int type)
#endif /* NO_RSA */
#ifdef HAVE_ECC
case ECDSAk:
algoSz = sizeof(ECDSA_AlgoID);
algoName = ECDSA_AlgoID;
algoSz = sizeof(ECC_AlgoID);
algoName = ECC_AlgoID;
tagSz = 0;
break;
#endif /* HAVE_ECC */
default:
@ -2399,8 +2484,9 @@ static word32 SetAlgoID(int algoOID, byte* output, int type)
return 0;
}
idSz = SetLength(algoSz - 2, ID_Length); /* don't include TAG_NULL/0 */
seqSz = SetSequence(idSz + algoSz + 1, seqArray);
idSz = SetLength(algoSz - tagSz, ID_Length); /* don't include tags */
seqSz = SetSequence(idSz + algoSz + 1 + curveSz, seqArray);
/* +1 for object id, curveID of curveSz follows for ecc */
seqArray[seqSz++] = ASN_OBJECT_ID;
XMEMCPY(output, seqArray, seqSz);
@ -2420,7 +2506,7 @@ word32 EncodeSignature(byte* out, const byte* digest, word32 digSz, int hashOID)
word32 encDigSz, algoSz, seqSz;
encDigSz = SetDigest(digest, digSz, digArray);
algoSz = SetAlgoID(hashOID, algoArray, hashType);
algoSz = SetAlgoID(hashOID, algoArray, hashType, 0);
seqSz = SetSequence(encDigSz + algoSz, seqArray);
XMEMCPY(out, seqArray, seqSz);
@ -3195,6 +3281,8 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
return ret;
}
CYASSL_MSG("Parsed Past Key");
if (cert->srcIdx != cert->sigIndex) {
if (cert->srcIdx < cert->sigIndex) {
/* save extensions */
@ -3626,8 +3714,59 @@ static int SetSerial(const byte* serial, byte* output)
}
#ifdef HAVE_ECC
/* Write a public ECC key to output */
static int SetEccPublicKey(byte* output, ecc_key* key)
{
byte algo[MAX_ALGO_SZ];
byte curve[MAX_ALGO_SZ];
byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */
byte pub[ECC_BUFSIZE];
int algoSz;
int curveSz;
int lenSz;
int idx;
word32 pubSz = sizeof(pub);
int ret = ecc_export_x963(key, pub, &pubSz);
if (ret != 0) return ret;
/* headers */
curveSz = SetCurve(key, curve);
if (curveSz <= 0) return curveSz;
algoSz = SetAlgoID(ECDSAk, algo, keyType, curveSz);
lenSz = SetLength(pubSz + 1, len);
len[lenSz++] = 0; /* trailing 0 */
/* write */
idx = SetSequence(pubSz + curveSz + lenSz + 1 + algoSz, output);
/* 1 is for ASN_BIT_STRING */
/* algo */
XMEMCPY(output + idx, algo, algoSz);
idx += algoSz;
/* curve */
XMEMCPY(output + idx, curve, curveSz);
idx += curveSz;
/* bit string */
output[idx++] = ASN_BIT_STRING;
/* length */
XMEMCPY(output + idx, len, lenSz);
idx += lenSz;
/* pub */
XMEMCPY(output + idx, pub, pubSz);
idx += pubSz;
return idx;
}
#endif /* HAVE_ECC */
/* Write a public RSA key to output */
static int SetPublicKey(byte* output, RsaKey* key)
static int SetRsaPublicKey(byte* output, RsaKey* key)
{
byte n[MAX_RSA_INT_SZ];
byte e[MAX_RSA_E_SZ];
@ -3673,7 +3812,7 @@ static int SetPublicKey(byte* output, RsaKey* key)
return BUFFER_E;
/* headers */
algoSz = SetAlgoID(RSAk, algo, keyType);
algoSz = SetAlgoID(RSAk, algo, keyType, 0);
seqSz = SetSequence(nSz + eSz, seq);
lenSz = SetLength(seqSz + nSz + eSz + 1, len);
len[lenSz++] = 0; /* trailing 0 */
@ -4039,9 +4178,10 @@ static int SetName(byte* output, CertName* name)
}
/* encode info from cert into DER enocder format */
static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, RNG* rng,
const byte* ntruKey, word16 ntruSz)
static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
RNG* rng, const byte* ntruKey, word16 ntruSz)
{
(void)eccKey;
(void)ntruKey;
(void)ntruSz;
@ -4057,18 +4197,31 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, RNG* rng,
der->serialSz = SetSerial(cert->serial, der->serial);
/* signature algo */
der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, sigType);
der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, sigType, 0);
if (der->sigAlgoSz == 0)
return ALGO_ID_E;
/* public key */
if (cert->keyType == RSA_KEY) {
der->publicKeySz = SetPublicKey(der->publicKey, rsaKey);
if (der->publicKeySz == 0)
if (rsaKey == NULL)
return PUBLIC_KEY_E;
der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey);
if (der->publicKeySz <= 0)
return PUBLIC_KEY_E;
}
else {
#ifdef HAVE_ECC
if (cert->keyType == ECC_KEY) {
if (eccKey == NULL)
return PUBLIC_KEY_E;
der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey);
if (der->publicKeySz <= 0)
return PUBLIC_KEY_E;
}
#endif /* HAVE_ECC */
#ifdef HAVE_NTRU
if (cert->keyType == NTRU_KEY) {
word32 rc;
word16 encodedSz;
@ -4085,8 +4238,8 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, RNG* rng,
return PUBLIC_KEY_E;
der->publicKeySz = encodedSz;
#endif
}
#endif /* HAVE_NTRU */
der->validitySz = 0;
#ifdef CYASSL_ALT_NAMES
@ -4257,7 +4410,7 @@ static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz,
int idx = bodySz, seqSz;
/* algo */
idx += SetAlgoID(sigAlgoType, buffer + idx, sigType);
idx += SetAlgoID(sigAlgoType, buffer + idx, sigType, 0);
/* bit string */
buffer[idx++] = ASN_BIT_STRING;
/* length */
@ -4278,13 +4431,17 @@ static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz,
/* Make an x509 Certificate v3 any key type from cert input, write to buffer */
static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
RsaKey* rsaKey, RNG* rng, const byte* ntruKey, word16 ntruSz)
RsaKey* rsaKey, ecc_key* eccKey, RNG* rng,
const byte* ntruKey, word16 ntruSz)
{
DerCert der;
int ret;
cert->keyType = rsaKey ? RSA_KEY : NTRU_KEY;
ret = EncodeCert(cert, &der, rsaKey, rng, ntruKey, ntruSz);
if (eccKey)
cert->keyType = ECC_KEY;
else
cert->keyType = rsaKey ? RSA_KEY : NTRU_KEY;
ret = EncodeCert(cert, &der, rsaKey, eccKey, rng, ntruKey, ntruSz);
if (ret != 0)
return ret;
@ -4295,10 +4452,11 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
}
/* Make an x509 Certificate v3 RSA from cert input, write to buffer */
int MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey,RNG* rng)
/* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */
int MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey,
ecc_key* eccKey, RNG* rng)
{
return MakeAnyCert(cert, derBuffer, derSz, rsaKey, rng, NULL, 0);
return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0);
}
@ -4307,7 +4465,7 @@ int MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey,RNG* rng)
int MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz,
const byte* ntruKey, word16 keySz, RNG* rng)
{
return MakeAnyCert(cert, derBuffer, derSz, NULL, rng, ntruKey, keySz);
return MakeAnyCert(cert, derBuffer, derSz, NULL, NULL, rng, ntruKey, keySz);
}
#endif /* HAVE_NTRU */
@ -4337,7 +4495,7 @@ int SignCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* rsaKey,
int MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, RNG* rng)
{
int ret = MakeCert(cert, buffer, buffSz, key, rng);
int ret = MakeCert(cert, buffer, buffSz, key, NULL, rng);
if (ret < 0)
return ret;
@ -5367,7 +5525,7 @@ int EncodeOcspRequest(OcspRequest* req)
CYASSL_ENTER("EncodeOcspRequest");
algoSz = SetAlgoID(SHAh, algoArray, hashType);
algoSz = SetAlgoID(SHAh, algoArray, hashType, 0);
req->issuerHash = req->cert->issuerHash;
issuerSz = SetDigest(req->cert->issuerHash, SHA_SIZE, issuerArray);

View File

@ -1997,7 +1997,6 @@ int ecc_export_x963(ecc_key* key, byte* out, word32* outLen)
int ecc_import_x963(const byte* in, word32 inLen, ecc_key* key)
{
int x, err;
if (in == NULL || key == NULL)
return ECC_BAD_ARG_E;

View File

@ -2798,7 +2798,7 @@ int rsa_test(void)
if (ret < 0)
return -405;
certSz = MakeCert(&myCert, derCert, FOURK_BUF, &key, &rng);
certSz = MakeCert(&myCert, derCert, FOURK_BUF, &key, NULL, &rng);
if (certSz < 0)
return -407;
@ -2886,7 +2886,7 @@ int rsa_test(void)
if (ret < 0)
return -5405;
certSz = MakeCert(&myCert, derCert, FOURK_BUF, &key, &rng);
certSz = MakeCert(&myCert, derCert, FOURK_BUF, NULL, &caKey, &rng);
if (certSz < 0)
return -5407;

View File

@ -151,9 +151,10 @@ enum Misc_ASN {
enum Oid_Types {
hashType = 0,
sigType = 1,
keyType = 2
hashType = 0,
sigType = 1,
keyType = 2,
curveType = 3
};
@ -400,7 +401,8 @@ enum cert_enums {
JOINT_LEN = 2,
EMAIL_JOINT_LEN = 9,
RSA_KEY = 10,
NTRU_KEY = 11
NTRU_KEY = 11,
ECC_KEY = 12
};

View File

@ -125,7 +125,8 @@ typedef struct Cert {
keyType = RSA_KEY (default)
*/
CYASSL_API void InitCert(Cert*);
CYASSL_API int MakeCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, RNG*);
CYASSL_API int MakeCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*,
ecc_key*, RNG*);
CYASSL_API int SignCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*,
ecc_key*, RNG*);
CYASSL_API int MakeSelfCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*,