From 72d11e19cd7fdfc759e0c0bcac5a775604dd5a33 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 29 Mar 2017 16:14:34 -0600 Subject: [PATCH 1/5] add create PKCS8 key --- wolfcrypt/src/asn.c | 153 ++++++++++++++++++++++++++++++++++++++++ wolfssl/wolfcrypt/asn.h | 5 ++ 2 files changed, 158 insertions(+) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 3114ef915..10bb3dc15 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -1934,6 +1934,159 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, } +/* PKCS#8 from RFC 5208 + * This function takes in a DER key and converts it to PKCS#8 format. Used + * in creating PKCS#12 shrouded key bags. + * Reverse of ToTraditional + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes optional + * } + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * Returns the size of PKCS#8 placed into out. In error cases returns negative + * values. + */ +int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, + int algoID, const byte* curveOID, word32 oidSz) +{ + word32 keyIdx = 0; + word32 tmpSz = 0; + word32 sz; + + + /* If out is NULL then return the max size needed + * + 2 for ASN_OBJECT_ID and ASN_OCTET_STRING tags */ + if (out == NULL && outSz != NULL) { + *outSz = keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2; + + if (curveOID != NULL) + *outSz += oidSz + MAX_LENGTH_SZ + 1; + + WOLFSSL_MSG("Checking size of PKCS8"); + + return LENGTH_ONLY_E; + } + + WOLFSSL_ENTER("wc_CreatePKCS8Key()"); + + if (key == NULL || out == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + /* check the buffer has enough room for largest possible size */ + if (curveOID != NULL) { + if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 3 + oidSz + MAX_LENGTH_SZ)) + return BUFFER_E; + } + else { + if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2)) + return BUFFER_E; + } + + /* PrivateKeyInfo ::= SEQUENCE */ + keyIdx += MAX_SEQ_SZ; /* save room for sequence */ + + /* version Version + * no header information just INTEGER */ + sz = SetMyVersion(PKCS8v0, out + keyIdx, 0); + tmpSz += sz; keyIdx += sz; + + /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier */ + sz = SetAlgoID(algoID, out + keyIdx, oidKeyType, 0); + tmpSz += sz; keyIdx += sz; + + /* privateKey PrivateKey * + * pkcs8 ecc uses slightly different format. Places curve oid in + * buffer */ + if (curveOID != NULL && oidSz > 0) { + out[keyIdx++] = ASN_OBJECT_ID; tmpSz++; + sz = SetLength(oidSz, out + keyIdx); + keyIdx += sz; tmpSz += sz; + XMEMCPY(out + keyIdx, curveOID, oidSz); + keyIdx += oidSz; tmpSz += keyIdx; + } + + out[keyIdx] = ASN_OCTET_STRING; + keyIdx++; tmpSz++; + + sz = SetLength(keySz, out + keyIdx); + keyIdx += sz; tmpSz += sz; + XMEMCPY(out + keyIdx, key, keySz); + tmpSz += keySz; + + /* attributes optional + * No attributes currently added */ + + /* rewind and add sequence */ + sz = SetSequence(tmpSz, out); + XMEMMOVE(out + sz, out + MAX_SEQ_SZ, tmpSz); + + return tmpSz + sz; +} + + +int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, + int* algoID, void* heap) +{ + word32 tmpIdx = 0; + + #ifdef HAVE_ECC + ecc_key ecc; + #endif + + #ifndef NO_RSA + RsaKey rsa; + + wc_InitRsaKey(&rsa, heap); + if (wc_RsaPrivateKeyDecode(key, &tmpIdx, &rsa, keySz) == 0) { + *algoID = RSAk; + } + else { + WOLFSSL_MSG("Not RSA DER key"); + } + wc_FreeRsaKey(&rsa); + #endif /* NO_RSA */ + #ifdef HAVE_ECC + if (algoID == 0) { + tmpIdx = 0; + wc_ecc_init_ex(&ecc, heap, INVALID_DEVID); + if (wc_EccPrivateKeyDecode(key, &tmpIdx, &ecc, keySz) == 0) { + *algoID = ECDSAk; + + /* now find oid */ + if (wc_ecc_get_oid(ecc.dp->oidSum, curveOID, oidSz) < 0) { + WOLFSSL_MSG("Error getting ECC curve OID"); + wc_ecc_free(&ecc); + return BAD_FUNC_ARG; + } + } + else { + WOLFSSL_MSG("Not ECC DER key either"); + } + wc_ecc_free(&ecc); + } + #endif /* HAVE_ECC */ + + /* if flag is not set then is neither RSA or ECC key that could be + * found */ + if (*algoID == 0) { + WOLFSSL_MSG("Bad key DER or compile options"); + return BAD_FUNC_ARG; + } + + return 1; +} + + /* Remove Encrypted PKCS8 header, move beginning of traditional to beginning of input */ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index f1419a1d2..a75573939 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -134,6 +134,7 @@ enum Misc_ASN { MAX_KEY_SIZE = 64, /* MAX PKCS Key length */ PKCS5 = 5, /* PKCS oid tag */ PKCS5v2 = 6, /* PKCS #5 v2.0 */ + PKCS8v0 = 0, /* default PKCS#8 version */ PKCS12 = 12, /* PKCS #12 */ MAX_UNICODE_SZ = 256, ASN_BOOL_SIZE = 2, /* including type */ @@ -684,6 +685,10 @@ WOLFSSL_LOCAL int ToTraditionalInline(const byte* input, word32* inOutIdx, word32 length); WOLFSSL_LOCAL int ToTraditionalEnc(byte* buffer, word32 length,const char*,int); WOLFSSL_LOCAL int DecryptContent(byte* input, word32 sz,const char* psw,int pswSz); +WOLFSSL_LOCAL int wc_CreatePKCS8Key(byte* out, word32* outSz, + byte* key, word32 keySz, int algoID, const byte* curveOID, word32 oidSz); +WOLFSSL_LOCAL int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, + word32* oidSz, int* algoID, void* heap); typedef struct tm wolfssl_tm; #if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) From 219fb584e28534c5c6a07cc16b8e87a223bda5ca Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Tue, 28 Mar 2017 10:36:33 -0600 Subject: [PATCH 2/5] fix for lenght of PKCS8 with ECC and for ECC get key algo ID --- wolfcrypt/src/asn.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 10bb3dc15..88dce6770 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -2012,7 +2012,7 @@ int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, sz = SetLength(oidSz, out + keyIdx); keyIdx += sz; tmpSz += sz; XMEMCPY(out + keyIdx, curveOID, oidSz); - keyIdx += oidSz; tmpSz += keyIdx; + keyIdx += oidSz; tmpSz += oidSz; } out[keyIdx] = ASN_OCTET_STRING; @@ -2042,10 +2042,16 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, #ifdef HAVE_ECC ecc_key ecc; #endif - #ifndef NO_RSA RsaKey rsa; + #endif + if (algoID == NULL) { + return BAD_FUNC_ARG; + } + *algoID = 0; + + #ifndef NO_RSA wc_InitRsaKey(&rsa, heap); if (wc_RsaPrivateKeyDecode(key, &tmpIdx, &rsa, keySz) == 0) { *algoID = RSAk; @@ -2056,12 +2062,19 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, wc_FreeRsaKey(&rsa); #endif /* NO_RSA */ #ifdef HAVE_ECC - if (algoID == 0) { + if (*algoID != RSAk) { tmpIdx = 0; wc_ecc_init_ex(&ecc, heap, INVALID_DEVID); if (wc_EccPrivateKeyDecode(key, &tmpIdx, &ecc, keySz) == 0) { *algoID = ECDSAk; + /* sanity check on arguments */ + if (curveOID == NULL || oidSz == NULL) { + WOLFSSL_MSG("Error getting ECC curve OID"); + wc_ecc_free(&ecc); + return BAD_FUNC_ARG; + } + /* now find oid */ if (wc_ecc_get_oid(ecc.dp->oidSum, curveOID, oidSz) < 0) { WOLFSSL_MSG("Error getting ECC curve OID"); From 5663fbf41a65286514307e4ec955e452667eab5c Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Tue, 28 Mar 2017 15:48:31 -0600 Subject: [PATCH 3/5] adjust placement of ECC curve OID in PKCS8 and add parameter notes --- wolfcrypt/src/asn.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 88dce6770..9143c6139 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -1949,6 +1949,14 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier * PrivateKey ::= OCTET STRING * + * out buffer to place result in + * outSz size of out buffer + * key buffer with DER key + * keySz size of key buffer + * algoID algorithm ID i.e. RSAk + * curveOID ECC curve oid if used. Should be NULL for RSA keys. + * oidSz size of curve oid. Is set to 0 if curveOID is NULL. + * * Returns the size of PKCS#8 placed into out. In error cases returns negative * values. */ @@ -1987,6 +1995,7 @@ int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, return BUFFER_E; } else { + oidSz = 0; /* with no curveOID oid size must be 0 */ if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2)) return BUFFER_E; @@ -2001,7 +2010,13 @@ int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, tmpSz += sz; keyIdx += sz; /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier */ - sz = SetAlgoID(algoID, out + keyIdx, oidKeyType, 0); + sz = 0; /* set sz to 0 and get privateKey oid buffer size needed */ + if (curveOID != NULL && oidSz > 0) { + byte buf[MAX_LENGTH_SZ]; + sz = SetLength(oidSz, buf); + sz += 1; /* plus one for ASN object id */ + } + sz = SetAlgoID(algoID, out + keyIdx, oidKeyType, oidSz + sz); tmpSz += sz; keyIdx += sz; /* privateKey PrivateKey * From 9ebfb0e953bd7ea76b664995dbce921606d10da4 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 29 Mar 2017 16:42:51 -0600 Subject: [PATCH 4/5] make the function wc_CreatePKCS8Key public --- wolfcrypt/src/asn.c | 3 +++ wolfssl/wolfcrypt/asn.h | 2 -- wolfssl/wolfcrypt/asn_public.h | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 9143c6139..94210812e 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -2111,6 +2111,9 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, return BAD_FUNC_ARG; } + (void)curveOID; + (void)oidSz; + return 1; } diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index a75573939..b7377b9fd 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -685,8 +685,6 @@ WOLFSSL_LOCAL int ToTraditionalInline(const byte* input, word32* inOutIdx, word32 length); WOLFSSL_LOCAL int ToTraditionalEnc(byte* buffer, word32 length,const char*,int); WOLFSSL_LOCAL int DecryptContent(byte* input, word32 sz,const char* psw,int pswSz); -WOLFSSL_LOCAL int wc_CreatePKCS8Key(byte* out, word32* outSz, - byte* key, word32 keySz, int algoID, const byte* curveOID, word32 oidSz); WOLFSSL_LOCAL int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, int* algoID, void* heap); diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 78c48c684..83eb3e78d 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -270,6 +270,8 @@ WOLFSSL_API int wc_GetCTC_HashOID(int type); WOLFSSL_API int wc_GetPkcs8TraditionalOffset(byte* input, word32* inOutIdx, word32 sz); +WOLFSSL_API int wc_CreatePKCS8Key(byte* out, word32* outSz, + byte* key, word32 keySz, int algoID, const byte* curveOID, word32 oidSz); /* Time */ /* Returns seconds (Epoch/UTC) From 71b75efd631656826b531b0ef6bdb238c69a2efb Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Thu, 30 Mar 2017 10:46:58 -0600 Subject: [PATCH 5/5] move PKCS8 create function and remove PWDBASED requirement --- wolfcrypt/src/asn.c | 230 ++++++++++++++++++++++---------------------- 1 file changed, 115 insertions(+), 115 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 94210812e..bf2f00744 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -1596,6 +1596,121 @@ int wc_GetPkcs8TraditionalOffset(byte* input, word32* inOutIdx, word32 sz) } +/* PKCS#8 from RFC 5208 + * This function takes in a DER key and converts it to PKCS#8 format. Used + * in creating PKCS#12 shrouded key bags. + * Reverse of ToTraditional + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes optional + * } + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * out buffer to place result in + * outSz size of out buffer + * key buffer with DER key + * keySz size of key buffer + * algoID algorithm ID i.e. RSAk + * curveOID ECC curve oid if used. Should be NULL for RSA keys. + * oidSz size of curve oid. Is set to 0 if curveOID is NULL. + * + * Returns the size of PKCS#8 placed into out. In error cases returns negative + * values. + */ +int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, + int algoID, const byte* curveOID, word32 oidSz) +{ + word32 keyIdx = 0; + word32 tmpSz = 0; + word32 sz; + + + /* If out is NULL then return the max size needed + * + 2 for ASN_OBJECT_ID and ASN_OCTET_STRING tags */ + if (out == NULL && outSz != NULL) { + *outSz = keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2; + + if (curveOID != NULL) + *outSz += oidSz + MAX_LENGTH_SZ + 1; + + WOLFSSL_MSG("Checking size of PKCS8"); + + return LENGTH_ONLY_E; + } + + WOLFSSL_ENTER("wc_CreatePKCS8Key()"); + + if (key == NULL || out == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + /* check the buffer has enough room for largest possible size */ + if (curveOID != NULL) { + if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 3 + oidSz + MAX_LENGTH_SZ)) + return BUFFER_E; + } + else { + oidSz = 0; /* with no curveOID oid size must be 0 */ + if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2)) + return BUFFER_E; + } + + /* PrivateKeyInfo ::= SEQUENCE */ + keyIdx += MAX_SEQ_SZ; /* save room for sequence */ + + /* version Version + * no header information just INTEGER */ + sz = SetMyVersion(PKCS8v0, out + keyIdx, 0); + tmpSz += sz; keyIdx += sz; + + /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier */ + sz = 0; /* set sz to 0 and get privateKey oid buffer size needed */ + if (curveOID != NULL && oidSz > 0) { + byte buf[MAX_LENGTH_SZ]; + sz = SetLength(oidSz, buf); + sz += 1; /* plus one for ASN object id */ + } + sz = SetAlgoID(algoID, out + keyIdx, oidKeyType, oidSz + sz); + tmpSz += sz; keyIdx += sz; + + /* privateKey PrivateKey * + * pkcs8 ecc uses slightly different format. Places curve oid in + * buffer */ + if (curveOID != NULL && oidSz > 0) { + out[keyIdx++] = ASN_OBJECT_ID; tmpSz++; + sz = SetLength(oidSz, out + keyIdx); + keyIdx += sz; tmpSz += sz; + XMEMCPY(out + keyIdx, curveOID, oidSz); + keyIdx += oidSz; tmpSz += oidSz; + } + + out[keyIdx] = ASN_OCTET_STRING; + keyIdx++; tmpSz++; + + sz = SetLength(keySz, out + keyIdx); + keyIdx += sz; tmpSz += sz; + XMEMCPY(out + keyIdx, key, keySz); + tmpSz += keySz; + + /* attributes optional + * No attributes currently added */ + + /* rewind and add sequence */ + sz = SetSequence(tmpSz, out); + XMEMMOVE(out + sz, out + MAX_SEQ_SZ, tmpSz); + + return tmpSz + sz; +} + + /* check that the private key is a pair for the public key in certificate * return 1 (true) on match * return 0 or negative value on failure/error @@ -1934,121 +2049,6 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, } -/* PKCS#8 from RFC 5208 - * This function takes in a DER key and converts it to PKCS#8 format. Used - * in creating PKCS#12 shrouded key bags. - * Reverse of ToTraditional - * - * PrivateKeyInfo ::= SEQUENCE { - * version Version, - * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - * privateKey PrivateKey, - * attributes optional - * } - * Version ::= INTEGER - * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier - * PrivateKey ::= OCTET STRING - * - * out buffer to place result in - * outSz size of out buffer - * key buffer with DER key - * keySz size of key buffer - * algoID algorithm ID i.e. RSAk - * curveOID ECC curve oid if used. Should be NULL for RSA keys. - * oidSz size of curve oid. Is set to 0 if curveOID is NULL. - * - * Returns the size of PKCS#8 placed into out. In error cases returns negative - * values. - */ -int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, - int algoID, const byte* curveOID, word32 oidSz) -{ - word32 keyIdx = 0; - word32 tmpSz = 0; - word32 sz; - - - /* If out is NULL then return the max size needed - * + 2 for ASN_OBJECT_ID and ASN_OCTET_STRING tags */ - if (out == NULL && outSz != NULL) { - *outSz = keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ - + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2; - - if (curveOID != NULL) - *outSz += oidSz + MAX_LENGTH_SZ + 1; - - WOLFSSL_MSG("Checking size of PKCS8"); - - return LENGTH_ONLY_E; - } - - WOLFSSL_ENTER("wc_CreatePKCS8Key()"); - - if (key == NULL || out == NULL || outSz == NULL) { - return BAD_FUNC_ARG; - } - - /* check the buffer has enough room for largest possible size */ - if (curveOID != NULL) { - if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ - + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 3 + oidSz + MAX_LENGTH_SZ)) - return BUFFER_E; - } - else { - oidSz = 0; /* with no curveOID oid size must be 0 */ - if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ - + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2)) - return BUFFER_E; - } - - /* PrivateKeyInfo ::= SEQUENCE */ - keyIdx += MAX_SEQ_SZ; /* save room for sequence */ - - /* version Version - * no header information just INTEGER */ - sz = SetMyVersion(PKCS8v0, out + keyIdx, 0); - tmpSz += sz; keyIdx += sz; - - /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier */ - sz = 0; /* set sz to 0 and get privateKey oid buffer size needed */ - if (curveOID != NULL && oidSz > 0) { - byte buf[MAX_LENGTH_SZ]; - sz = SetLength(oidSz, buf); - sz += 1; /* plus one for ASN object id */ - } - sz = SetAlgoID(algoID, out + keyIdx, oidKeyType, oidSz + sz); - tmpSz += sz; keyIdx += sz; - - /* privateKey PrivateKey * - * pkcs8 ecc uses slightly different format. Places curve oid in - * buffer */ - if (curveOID != NULL && oidSz > 0) { - out[keyIdx++] = ASN_OBJECT_ID; tmpSz++; - sz = SetLength(oidSz, out + keyIdx); - keyIdx += sz; tmpSz += sz; - XMEMCPY(out + keyIdx, curveOID, oidSz); - keyIdx += oidSz; tmpSz += oidSz; - } - - out[keyIdx] = ASN_OCTET_STRING; - keyIdx++; tmpSz++; - - sz = SetLength(keySz, out + keyIdx); - keyIdx += sz; tmpSz += sz; - XMEMCPY(out + keyIdx, key, keySz); - tmpSz += keySz; - - /* attributes optional - * No attributes currently added */ - - /* rewind and add sequence */ - sz = SetSequence(tmpSz, out); - XMEMMOVE(out + sz, out + MAX_SEQ_SZ, tmpSz); - - return tmpSz + sz; -} - - int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, int* algoID, void* heap) {