From fbedabe6012c22b0d2c1151a630b0f3c9ba3e742 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 13 Dec 2019 19:34:14 +0100 Subject: [PATCH] OpenSSH changes - increase FP_MAX_BITS for OpenSSH - Add helpful loggin API (names are self-explanatory) -- wolfSSL_GetLoggingCb -- WOLFSSL_IS_DEBUG_ON - Define WOLFSSL_EC_METHOD as an alias of WOLFSSL_EC_GROUP - Add wolfSSL_EC_GROUP_method_of which really just returns the group itself - Add wolfSSL_EC_METHOD_get_field_type which gets the curve type of the WOLFSSL_EC_GROUP(remember that WOLFSSL_EC_METHOD is an alias of WOLFSSL_EC_GROUP for now) - Modify Base64_Decode so that it accepts arbitrary PEM line length - Modify PemToDer so that it accepts private keys with a custom -----BEGIN * PRIVATE KEY----- header --- src/ssl.c | 47 ++++++++++++++++++++++-- wolfcrypt/src/asn.c | 72 ++++++++++++++++++++++++++++++++++--- wolfcrypt/src/coding.c | 69 ++++++++++++++++++++++------------- wolfcrypt/src/logging.c | 11 ++++++ wolfcrypt/test/test.c | 2 +- wolfssl/openssl/ec.h | 11 ++++++ wolfssl/openssl/ssl.h | 2 -- wolfssl/ssl.h | 2 ++ wolfssl/wolfcrypt/logging.h | 3 ++ wolfssl/wolfcrypt/tfm.h | 5 +++ 10 files changed, 189 insertions(+), 35 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index f20ec0a8b..ed045b6b9 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -30002,7 +30002,12 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) } if (rng) { - pubSz = privSz = wolfSSL_BN_num_bytes(dh->p); + pubSz = wolfSSL_BN_num_bytes(dh->p); + if (dh->length) { + privSz = dh->length/8; /* to bytes */ + } else { + privSz = pubSz; + } pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_PRIVATE_KEY); if (pub == NULL || priv == NULL) { @@ -33219,6 +33224,12 @@ static int SetECKeyInternal(WOLFSSL_EC_KEY* eckey) return WOLFSSL_FATAL_ERROR; } + /* copy over the public point to key */ + if (wc_ecc_copy_point((ecc_point*)eckey->pub_key->internal, &key->pubkey) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_copy_point error"); + return WOLFSSL_FATAL_ERROR; + } + /* public key */ key->type = ECC_PUBLICKEY; } @@ -33306,6 +33317,11 @@ WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key) return NULL; } + if (wolfSSL_BN_is_zero(key->priv_key)) { + /* return NULL if not set */ + return NULL; + } + return key->priv_key; } @@ -33738,7 +33754,12 @@ int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key, return WOLFSSL_FAILURE; } - if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) { + if (SetECPointExternal(key->pub_key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return WOLFSSL_FAILURE; + } + + if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetECKeyInternal failed"); return WOLFSSL_FAILURE; } @@ -33894,6 +33915,10 @@ void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p) WOLFSSL_ENTER("wolfSSL_EC_POINT_dump"); + if (!WOLFSSL_IS_DEBUG_ON() || wolfSSL_GetLoggingCb()) { + return; + } + if (p == NULL) { printf("%s = NULL", msg); return; @@ -33944,6 +33969,20 @@ int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b, #endif /* OPENSSL_EXTRA */ #if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +const WOLFSSL_EC_METHOD* wolfSSL_EC_GROUP_method_of( + const WOLFSSL_EC_GROUP *group) +{ + return group; +} + +int wolfSSL_EC_METHOD_get_field_type(const WOLFSSL_EC_METHOD *meth) +{ + if (meth) { + return NID_X9_62_prime_field; + } + return WOLFSSL_FAILURE; +} + void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group) { WOLFSSL_ENTER("wolfSSL_EC_GROUP_free"); @@ -34661,7 +34700,7 @@ int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group, return WOLFSSL_FAILURE; } - return WOLFSSL_SUCCESS; + return ret; } /* End EC_POINT */ @@ -46407,6 +46446,8 @@ WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* str, int len, wolfSSL_BN_free(ret); return NULL; } + } else { + return NULL; } return ret; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 3f27159bf..ac5403e42 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -9759,6 +9759,11 @@ const char* const END_ENC_PRIV_KEY = "-----END ENCRYPTED PRIVATE KEY-----"; const char* const BEGIN_DSA_PRIV = "-----BEGIN DSA PRIVATE KEY-----"; const char* const END_DSA_PRIV = "-----END DSA PRIVATE KEY-----"; #endif +#ifdef OPENSSL_EXTRA + const char BEGIN_PRIV_KEY_PREFIX[] = "-----BEGIN"; + const char PRIV_KEY_SUFFIX[] = "PRIVATE KEY-----"; + const char END_PRIV_KEY_PREFIX[] = "-----END"; +#endif const char* const BEGIN_PUB_KEY = "-----BEGIN PUBLIC KEY-----"; const char* const END_PUB_KEY = "-----END PUBLIC KEY-----"; #ifdef HAVE_ED25519 @@ -10216,6 +10221,8 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, #ifdef WOLFSSL_PEM_TO_DER +#define STR_SIZEOF(x) (sizeof(x) - 1) /* -1 to not count the null char */ + /* Remove PEM header/footer, convert to ASN1, store any encrypted data info->consumed tracks of PEM bytes consumed in case multiple parts */ int PemToDer(const unsigned char* buff, long longSz, int type, @@ -10238,6 +10245,10 @@ int PemToDer(const unsigned char* buff, long longSz, int type, int padVal = 0; #endif #endif +#ifdef OPENSSL_EXTRA + char beginBuf[PEM_LINE_LEN]; + char endBuf[PEM_LINE_LEN]; +#endif WOLFSSL_ENTER("PemToDer"); @@ -10293,12 +10304,59 @@ int PemToDer(const unsigned char* buff, long longSz, int type, } if (!headerEnd) { +#ifdef OPENSSL_EXTRA + char* beginEnd; + int endLen; + /* see if there is a -----BEGIN * PRIVATE KEY----- header */ + headerEnd = XSTRNSTR((char*)buff, PRIV_KEY_SUFFIX, sz); + if (headerEnd) { + beginEnd = headerEnd + STR_SIZEOF(PRIV_KEY_SUFFIX); + /* back up to BEGIN_PRIV_KEY_PREFIX */ + headerEnd -= STR_SIZEOF(BEGIN_PRIV_KEY_PREFIX); + while (headerEnd > (char*)buff && + XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX, + STR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0) { + headerEnd--; + } + if (XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX, + STR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0 || + beginEnd - headerEnd > PEM_LINE_LEN) { + WOLFSSL_MSG("Couldn't find PEM header"); + return ASN_NO_PEM_HEADER; + } + /* headerEnd now points to beginning of header */ + XMEMCPY(beginBuf, headerEnd, beginEnd - headerEnd); + beginBuf[beginEnd - headerEnd] = '\0'; + /* look for matching footer */ + footer = XSTRNSTR(beginEnd, + beginBuf + STR_SIZEOF(BEGIN_PRIV_KEY_PREFIX), + (char*)buff + sz - beginEnd); + if (!footer) { + WOLFSSL_MSG("Couldn't find PEM footer"); + return ASN_NO_PEM_HEADER; + } + footer -= STR_SIZEOF(END_PRIV_KEY_PREFIX); + endLen = beginEnd - headerEnd - + (STR_SIZEOF(BEGIN_PRIV_KEY_PREFIX) - + STR_SIZEOF(END_PRIV_KEY_PREFIX)); + XMEMCPY(endBuf, footer, endLen); + endBuf[endLen] = '\0'; + + header = beginBuf; + footer = endBuf; + headerEnd = beginEnd; + } else { + WOLFSSL_MSG("Couldn't find PEM header"); + return ASN_NO_PEM_HEADER; + } +#else WOLFSSL_MSG("Couldn't find PEM header"); return ASN_NO_PEM_HEADER; +#endif + } else { + headerEnd += XSTRLEN(header); } - headerEnd += XSTRLEN(header); - /* eat end of line characters */ headerEnd = SkipEndOfLineChars(headerEnd, bufferEnd); @@ -10306,8 +10364,9 @@ int PemToDer(const unsigned char* buff, long longSz, int type, /* keyFormat is Key_Sum enum */ if (keyFormat) { #ifdef HAVE_ECC - if (header == BEGIN_EC_PRIV) - *keyFormat = ECDSAk; + *eccKey = (header == BEGIN_EC_PRIV || header == beginBuf) ? 1 : 0; + #else + *eccKey = 0; #endif #if !defined(NO_DSA) if (header == BEGIN_DSA_PRIV) @@ -10327,7 +10386,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, #endif /* WOLFSSL_ENCRYPTED_KEYS */ /* find footer */ - footerEnd = XSTRNSTR((char*)buff, footer, sz); + footerEnd = XSTRNSTR(headerEnd, footer, (char*)buff + sz - headerEnd); if (!footerEnd) { if (info) info->consumed = longSz; /* No more certs if no footer */ @@ -10363,6 +10422,9 @@ int PemToDer(const unsigned char* buff, long longSz, int type, return BUFFER_E; if ((header == BEGIN_PRIV_KEY +#ifdef OPENSSL_EXTRA + || header == beginBuf +#endif #ifdef HAVE_ECC || header == BEGIN_EC_PRIV #endif diff --git a/wolfcrypt/src/coding.c b/wolfcrypt/src/coding.c index 3aa59f0f3..c81588957 100644 --- a/wolfcrypt/src/coding.c +++ b/wolfcrypt/src/coding.c @@ -57,27 +57,66 @@ const byte base64Decode[] = { 62, BAD, BAD, BAD, 63, /* + starts at 0x2B */ 46, 47, 48, 49, 50, 51 }; +static WC_INLINE int Base64_SkipNewline(const byte* in, word32 *outLen, word32 *outJ) +{ + word32 inLen = *outLen; + word32 j = *outJ; + if (inLen && (in[j] == ' ' || in[j] == '\r' || in[j] == '\n')) { + byte endLine = in[j++]; + inLen--; + while (inLen && endLine == ' ') { /* allow trailing whitespace */ + endLine = in[j++]; + inLen--; + } + if (endLine == '\r') { + if (inLen) { + endLine = in[j++]; + inLen--; + } + } + if (endLine != '\n') { + WOLFSSL_MSG("Bad end of line in Base64 Decode"); + return ASN_INPUT_E; + } + } + *outLen = inLen; + *outJ = j; + return 0; +} int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) { word32 i = 0; word32 j = 0; word32 plainSz = inLen - ((inLen + (PEM_LINE_SZ - 1)) / PEM_LINE_SZ ); + int ret; const byte maxIdx = (byte)sizeof(base64Decode) + BASE64_MIN - 1; plainSz = (plainSz * 3 + 3) / 4; if (plainSz > *outLen) return BAD_FUNC_ARG; while (inLen > 3) { - byte b1, b2, b3; - byte e1 = in[j++]; - byte e2 = in[j++]; - byte e3 = in[j++]; - byte e4 = in[j++]; - int pad3 = 0; int pad4 = 0; + byte b1, b2, b3; + if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) { + return ret; + } + byte e1 = in[j++]; + if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) { + return ret; + } + byte e2 = in[j++]; + if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) { + return ret; + } + byte e3 = in[j++]; + if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) { + return ret; + } + byte e4 = in[j++]; + if (e1 == 0) /* end file 0's */ break; if (e3 == PAD) @@ -118,24 +157,6 @@ int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) break; inLen -= 4; - if (inLen && (in[j] == ' ' || in[j] == '\r' || in[j] == '\n')) { - byte endLine = in[j++]; - inLen--; - while (inLen && endLine == ' ') { /* allow trailing whitespace */ - endLine = in[j++]; - inLen--; - } - if (endLine == '\r') { - if (inLen) { - endLine = in[j++]; - inLen--; - } - } - if (endLine != '\n') { - WOLFSSL_MSG("Bad end of line in Base64 Decode"); - return ASN_INPUT_E; - } - } } /* If the output buffer has a room for an extra byte, add a null terminator */ if (out && *outLen > i) diff --git a/wolfcrypt/src/logging.c b/wolfcrypt/src/logging.c index 909062705..70d53121b 100644 --- a/wolfcrypt/src/logging.c +++ b/wolfcrypt/src/logging.c @@ -137,6 +137,12 @@ int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb f) #endif } +/* allow this to be set to NULL, so logs can be redirected to default output */ +wolfSSL_Logging_cb wolfSSL_GetLoggingCb(void) +{ + return log_function; +} + int wolfSSL_Debugging_ON(void) { @@ -346,6 +352,11 @@ void WOLFSSL_LEAVE(const char* msg, int ret) wolfssl_log(LEAVE_LOG , buffer); } } + +WOLFSSL_API int WOLFSSL_IS_DEBUG_ON(void) +{ + return loggingEnabled; +} #endif /* !WOLFSSL_DEBUG_ERRORS_ONLY */ #endif /* DEBUG_WOLFSSL */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index e8217ba09..d0e28fbe5 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -1383,7 +1383,7 @@ int base64_test(void) #endif const byte badSmall[] = "AAA Gdj="; const byte badLarge[] = "AAA~Gdj="; - const byte badEOL[] = "A+Gd "; + const byte badEOL[] = "A+Gd AA"; int i; /* Good Base64 encodings. */ diff --git a/wolfssl/openssl/ec.h b/wolfssl/openssl/ec.h index a8ef9d0c2..25640af2b 100644 --- a/wolfssl/openssl/ec.h +++ b/wolfssl/openssl/ec.h @@ -76,11 +76,14 @@ typedef struct WOLFSSL_EC_KEY WOLFSSL_EC_KEY; typedef struct WOLFSSL_EC_POINT WOLFSSL_EC_POINT; typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_GROUP; typedef struct WOLFSSL_EC_BUILTIN_CURVE WOLFSSL_EC_BUILTIN_CURVE; +/* WOLFSSL_EC_METHOD is just an alias of WOLFSSL_EC_GROUP for now */ +typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_METHOD; #define WOLFSSL_EC_TYPE_DEFINED #endif typedef WOLFSSL_EC_KEY EC_KEY; typedef WOLFSSL_EC_GROUP EC_GROUP; +typedef WOLFSSL_EC_GROUP EC_METHOD; typedef WOLFSSL_EC_POINT EC_POINT; typedef WOLFSSL_EC_BUILTIN_CURVE EC_builtin_curve; @@ -200,6 +203,11 @@ int wolfSSL_EC_GROUP_order_bits(const WOLFSSL_EC_GROUP *group); WOLFSSL_API void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group); WOLFSSL_API +const WOLFSSL_EC_METHOD* wolfSSL_EC_GROUP_method_of( + const WOLFSSL_EC_GROUP *group); +WOLFSSL_API +int wolfSSL_EC_METHOD_get_field_type(const WOLFSSL_EC_METHOD *meth); +WOLFSSL_API WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group); WOLFSSL_API int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group, @@ -265,6 +273,9 @@ char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, #define EC_GROUP_get_degree wolfSSL_EC_GROUP_get_degree #define EC_GROUP_get_order wolfSSL_EC_GROUP_get_order #define EC_GROUP_order_bits wolfSSL_EC_GROUP_order_bits +#define EC_GROUP_method_of wolfSSL_EC_GROUP_method_of + +#define EC_METHOD_get_field_type wolfSSL_EC_METHOD_get_field_type #define EC_POINT_new wolfSSL_EC_POINT_new #define EC_POINT_free wolfSSL_EC_POINT_free diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 8df5e400b..18dfc6779 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -1207,8 +1207,6 @@ enum { #define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b) #define TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9) -#define EC_METHOD_get_field_type(x) -1 - #define EVP_CIPHER_mode WOLFSSL_CIPHER_mode /* WOLFSSL_EVP_CIPHER is just the string name of the cipher */ #define EVP_CIPHER_name(x) x diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 8d5045b6f..b2f3f52e8 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -151,6 +151,8 @@ typedef struct WOLFSSL_EC_KEY WOLFSSL_EC_KEY; typedef struct WOLFSSL_EC_POINT WOLFSSL_EC_POINT; typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_GROUP; typedef struct WOLFSSL_EC_BUILTIN_CURVE WOLFSSL_EC_BUILTIN_CURVE; +/* WOLFSSL_EC_METHOD is just an alias of WOLFSSL_EC_GROUP for now */ +typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_METHOD; #define WOLFSSL_EC_TYPE_DEFINED #endif diff --git a/wolfssl/wolfcrypt/logging.h b/wolfssl/wolfcrypt/logging.h index ea1d88087..51d9b23b9 100644 --- a/wolfssl/wolfcrypt/logging.h +++ b/wolfssl/wolfcrypt/logging.h @@ -93,6 +93,7 @@ typedef void (*wolfSSL_Logging_cb)(const int logLevel, const char *const logMessage); WOLFSSL_API int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb log_function); +WOLFSSL_API wolfSSL_Logging_cb wolfSSL_GetLoggingCb(void); /* turn logging on, only if compiled in */ WOLFSSL_API int wolfSSL_Debugging_ON(void); @@ -148,6 +149,7 @@ WOLFSSL_API void wolfSSL_Debugging_OFF(void); WOLFSSL_API void WOLFSSL_LEAVE(const char* msg, int ret); #define WOLFSSL_STUB(m) \ WOLFSSL_MSG(WOLFSSL_LOG_CAT(wolfSSL Stub, m, not implemented)) + WOLFSSL_API int WOLFSSL_IS_DEBUG_ON(void); WOLFSSL_API void WOLFSSL_MSG(const char* msg); WOLFSSL_API void WOLFSSL_BUFFER(const byte* buffer, word32 length); @@ -157,6 +159,7 @@ WOLFSSL_API void wolfSSL_Debugging_OFF(void); #define WOLFSSL_ENTER(m) #define WOLFSSL_LEAVE(m, r) #define WOLFSSL_STUB(m) + #define WOLFSSL_IS_DEBUG_ON() 0 #define WOLFSSL_MSG(m) #define WOLFSSL_BUFFER(b, l) diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index 3ad33e11b..961472cff 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -258,6 +258,11 @@ #ifndef FP_MAX_BITS #define FP_MAX_BITS 4096 #endif +#ifdef WOLFSSL_OPENSSH + /* OpenSSH uses some BIG primes so we need to accommodate for that */ + #undef FP_MAX_BITS + #define FP_MAX_BITS 16384 +#endif #define FP_MAX_SIZE (FP_MAX_BITS+(8*DIGIT_BIT)) /* will this lib work? */