From efc2bb43d2f1b3595139c11df7e7bee201723186 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 16 Mar 2017 15:09:24 -0600 Subject: [PATCH] add wc_GetPkcs8TraditionalOffset() --- certs/server-keyPkcs8.der | Bin 0 -> 1219 bytes tests/api.c | 53 ++++++++++++++++++++ wolfcrypt/src/asn.c | 87 ++++++++++++++++++++++++--------- wolfssl/wolfcrypt/asn.h | 2 + wolfssl/wolfcrypt/asn_public.h | 3 ++ 5 files changed, 122 insertions(+), 23 deletions(-) create mode 100644 certs/server-keyPkcs8.der diff --git a/certs/server-keyPkcs8.der b/certs/server-keyPkcs8.der new file mode 100644 index 0000000000000000000000000000000000000000..5a5873543466614225e07a472bd26f158d8872f1 GIT binary patch literal 1219 zcmV;!1U&mNf&{+;0RS)!1_>&LNQUrsW5^Br2+u}0)hbn0Kk<9;a5TO zac#HKML{P4WyVFW^1LK4xRuT?PS*Auh`fBC`>1Ds{#=|g73;pSn3#nP7F+0aj|*8&3p009Dm0RaG- z&@>NHVg*nE@1N~tZoVb1>CD z*rKe4LoUSiWL`gsbq^8PQ6)~F*s7z>V6) zEL3(mBV)-BGPjehuf7>|mVspEwYZ5wLD6l{92@u>tZB`^clFrV6j(7Us6w5 zI#qu%z!^hOKd#Pi7xNCEK*~<76+6j!>A+byb8wsre91aUGN;%{bqa;T!u=I<+L;L| zX_}u3alfzxri^-8Z%A5HJI1k77vJXsfq?+aliqg~UAJ6ZeAtkwm@U?64r8;U+@{Qn zYNVnPjE;LqEV4^C+y)qZ>i%}2)S>A=4b2;0uV0>)TU!sIe6O>cklR;tI_0Su8^nN;-MFwz0r&hq!A{2I>*ke$MkkjJ7ft8XmL5DdS zLkk$CQy)1RUmrufhicz$(;@)=BA9Sa8W|}9fq?*uK~^YHo?q0S3p<#jRPtV zFhk(+cy#??8%znz=4dK$tsLJ&yjI(#q`oz9q+ZWY`~X#%Iz1!LXIk|l__Zm}L=o#X hE=Ionju^6EsJ|I9q4nGY=6sqT41B4u4k0%?@vt|dO7Z{z literal 0 HcmV?d00001 diff --git a/tests/api.c b/tests/api.c index 5431d1b39..7fb55c6e1 100644 --- a/tests/api.c +++ b/tests/api.c @@ -36,6 +36,9 @@ #ifdef HAVE_ECC #include /* wc_ecc_fp_free */ #endif +#ifndef NO_ASN + #include +#endif #include #include @@ -3026,6 +3029,52 @@ static void test_wolfSSL_BIO(void) } +/*----------------------------------------------------------------------------* + | wolfCrypt ASN + *----------------------------------------------------------------------------*/ + +static void test_wc_GetPkcs8TraditionalOffset(void) +{ +#if !defined(NO_ASN) && !defined(NO_FILESYSTEM) + int length, derSz; + word32 inOutIdx; + const char* path = "./certs/server-keyPkcs8.der"; + FILE* file; + byte der[2048]; + + printf(testingFmt, "wc_GetPkcs8TraditionalOffset"); + + file = fopen(path, "rb"); + AssertNotNull(file); + derSz = (int)fread(der, 1, sizeof(der), file); + fclose(file); + + /* valid case */ + inOutIdx = 0; + length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, derSz); + AssertIntGT(length, 0); + + /* inOutIdx > sz */ + inOutIdx = 4000; + length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, derSz); + AssertIntEQ(length, BAD_FUNC_ARG); + + /* null input */ + inOutIdx = 0; + length = wc_GetPkcs8TraditionalOffset(NULL, &inOutIdx, 0); + AssertIntEQ(length, BAD_FUNC_ARG); + + /* invalid input, fill buffer with 1's */ + XMEMSET(der, 1, sizeof(der)); + inOutIdx = 0; + length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, derSz); + AssertIntEQ(length, ASN_PARSE_E); + + printf(resultFmt, passed); +#endif /* NO_ASN */ +} + + /*----------------------------------------------------------------------------* | Main *----------------------------------------------------------------------------*/ @@ -3086,6 +3135,10 @@ void ApiTest(void) test_wolfSSL_BIO(); AssertIntEQ(test_wolfSSL_Cleanup(), SSL_SUCCESS); + + /* wolfCrypt ASN tests */ + test_wc_GetPkcs8TraditionalOffset(); + printf(" End API Tests\n"); } diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index a6e5e4935..c23cf87b9 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -1520,34 +1520,58 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, #endif /* HAVE_USER_RSA */ #endif /* NO_RSA */ +/* Remove PKCS8 header, place inOutIdx at beginning of traditional, + * return traditional length on success, negative on error */ +int ToTraditionalInline(const byte* input, word32* inOutIdx, word32 sz) +{ + word32 idx, oid; + int version, length; + + if (input == NULL || inOutIdx == NULL) + return BAD_FUNC_ARG; + + idx = *inOutIdx; + + if (GetSequence(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(input, &idx, &version, sz) < 0) + return ASN_PARSE_E; + + if (GetAlgoId(input, &idx, &oid, oidKeyType, sz) < 0) + return ASN_PARSE_E; + + if (input[idx] == ASN_OBJECT_ID) { + /* pkcs8 ecc uses slightly different format */ + idx++; /* past id */ + if (GetLength(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + idx += length; /* over sub id, key input will verify */ + } + + if (input[idx++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + *inOutIdx = idx; + + return length; +} + /* Remove PKCS8 header, move beginning of traditional to beginning of input */ int ToTraditional(byte* input, word32 sz) { - word32 inOutIdx = 0, oid; - int version, length; + word32 inOutIdx = 0; + int length; - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; + if (input == NULL) + return BAD_FUNC_ARG; - if (GetMyVersion(input, &inOutIdx, &version, sz) < 0) - return ASN_PARSE_E; - - if (GetAlgoId(input, &inOutIdx, &oid, oidKeyType, sz) < 0) - return ASN_PARSE_E; - - if (input[inOutIdx] == ASN_OBJECT_ID) { - /* pkcs8 ecc uses slightly different format */ - inOutIdx++; /* past id */ - if (GetLength(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; - inOutIdx += length; /* over sub id, key input will verify */ - } - - if (input[inOutIdx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; - - if (GetLength(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; + length = ToTraditionalInline(input, &inOutIdx, sz); + if (length < 0) + return length; XMEMMOVE(input, input + inOutIdx, length); @@ -1555,6 +1579,23 @@ int ToTraditional(byte* input, word32 sz) } +/* find beginning of traditional key inside PKCS#8 unencrypted buffer + * return traditional length on success, with inOutIdx at beginning of + * traditional + * return negative on failure/error */ +int wc_GetPkcs8TraditionalOffset(byte* input, word32* inOutIdx, word32 sz) +{ + int length; + + if (input == NULL || inOutIdx == NULL || (*inOutIdx > sz)) + return BAD_FUNC_ARG; + + length = ToTraditionalInline(input, inOutIdx, sz); + + return length; +} + + /* 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 diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 23930faeb..f1419a1d2 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -680,6 +680,8 @@ WOLFSSL_LOCAL void FreeTrustedPeerTable(TrustedPeerCert**, int, void*); #endif /* WOLFSSL_TRUST_PEER_CERT */ WOLFSSL_ASN_API int ToTraditional(byte* buffer, word32 length); +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); diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 242018ad7..78c48c684 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -268,6 +268,9 @@ WOLFSSL_API word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz, int hashOID); WOLFSSL_API int wc_GetCTC_HashOID(int type); +WOLFSSL_API int wc_GetPkcs8TraditionalOffset(byte* input, + word32* inOutIdx, word32 sz); + /* Time */ /* Returns seconds (Epoch/UTC) * timePtr: is "time_t", which is typically "long"