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 zcmXqLV%g8c$Y8+B#;Mij(e|B}k&%&=fu)IMr9l(RQYJ%9D$Lz} z$<sd-#mjmmRx;(TKP<_pw?p9Zu`>=^G8elUXSU}Z*)6{8^NYJ{i}zIPD{lRp z7Ra+VWb?z^c$q!Q#TPl5J4G%D>`XbVbz$K&uRRa1NJSrCaNuBa1;2~Afzh-EBju?J z%XbN1nqK@UR`p~S?_tY?C0jORIyrH^yuq=@SYdO7((+ZWk34*q*nITTwEH(N_^-Xr z#LURR2o8x^7fkqrl2`*6-_L)Wl6UCHEvZi}*Cz>hOgi#1>veZ&&aq01PbZ7K+EPNM zmY+U6Ywq?dvP&3F%=3G4_xP@Kv4bUhR$iOZuWcap`|W*2R^^*smV0Mpr_S1O=Sc0l zWzM2{w)HI;>vE=y=HB2YbBOlf?2%37_WozWB21b@Dx}>5cDwa-M~n1Zr!TdeUhcq8dIKa-O=gfcro{a zjPwubHJPW)Y*K3Pe39I7IALSBM|_Zfq*Z9W(E&;40Q+_4^2I;%&38EEw^r2pWaY~P zkru@TbGT|wT6q{Pzu{TR)q3dAU(w=QGdZ;~XU*p-+`oZkSx;3|zDHDu^|6h?;`g6} z+;DpGy>ijm?J+SmHzur{p?fWpFM0FgJIl^=XDwMI)YDh(p|i=`{0^H$?W=!f3$HAE zY0rCBI(~ipylK(V{0nQ=Z=OBjc6hPX+YQPt>m2>%*`0)yeNO-SBC_P__jzVD(eqc> z9Bhp*xn!yP|3b_C--V>JlA&X}rIa(b#L{4SOR0Ey=RNIN z_wz0*G5k}SQQ#*fsR?pJmt&Yl;Jo-N^SG^NEDrgU6Lw|Q%S_`|6`osHcyy2K_h-tq zsJZg&j?dfcVuFY57@i+iI}pfpZ+GdO{IEGypZngQ?>ee|=@wg-%gN$@c{AI8MDP1p z^DK3%f6j-KNB@hR>XsIN6k)r_d^O{q{SN1Xd-~qKe-}CTLGrVjxUYTQAFU5EH8%LV z{&eU$8vR8}s%y(9nKjujdBV)L`xQ;Q`n2oPqyHa2N(kGwaqhTLw)~__VbBx<=La7v zO8zEF`*5ClmZ4R+R_4C*p0L|Xm+UhwSQ2;M{|`gxOe /* 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"