Merge pull request #4282 from miyazakh/SSL_CIPHER_xx

Add SSL_CIPHER_get_xxx_nid support
This commit is contained in:
Chris Conlon
2021-08-13 13:48:31 -06:00
committed by GitHub
7 changed files with 476 additions and 32 deletions

View File

@ -20722,6 +20722,61 @@ const char* GetCipherNameInternal(const byte cipherSuite0, const byte cipherSuit
}
#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
/* Segment cipher name into n[n0,n1,n2,n4]
* @param cipher a pointer to WOLFSSL_CIPHER
* @param n return segment cipher name
* return cipher name if cipher is in the list,
* otherwise NULL
*/
const char* GetCipherSegment(const WOLFSSL_CIPHER* cipher, char n[][MAX_SEGMENT_SZ])
{
int i,j,k;
int strLen;
unsigned long offset;
const char* name;
/* sanity check */
if (cipher == NULL || n == NULL)
return NULL;
offset = cipher->offset;
if (offset >= (unsigned long)GetCipherNamesSize())
return NULL;
name = cipher_names[offset].name;
if (name == NULL)
return NULL;
/* Segment cipher name into n[n0,n1,n2,n4]
* These are used later for comparisons to create:
* keaStr, authStr, encStr, macStr
*
* If cipher_name = ECDHE-ECDSA-AES256-SHA
* then n0 = "ECDHE", n1 = "ECDSA", n2 = "AES256", n3 = "SHA"
* and n = [n0,n1,n2,n3,0]
*/
strLen = (int)XSTRLEN(name);
for (i = 0, j = 0, k = 0; i <= strLen; i++) {
if (k >= MAX_SEGMENTS || j >= MAX_SEGMENT_SZ)
break;
if (name[i] != '-' && name[i] != '\0') {
n[k][j] = name[i]; /* Fill kth segment string until '-' */
j++;
}
else {
n[k][j] = '\0';
j = 0;
k++;
}
}
return name;
}
const char* GetCipherKeaStr(char n[][MAX_SEGMENT_SZ]) {
const char* keaStr = NULL;
const char *n0,*n1,*n2,*n3,*n4;
@ -20866,7 +20921,32 @@ const char* GetCipherEncStr(char n[][MAX_SEGMENT_SZ]) {
return encStr;
}
/* Check if a cipher is AEAD
* @param n return segment cipher name
* return 1 if the cipher is AEAD, otherwise 0
*/
int IsCipherAEAD(char n[][MAX_SEGMENT_SZ])
{
const char *n1,*n2,*n3;
n1 = n[1];
n2 = n[2];
n3 = n[3];
WOLFSSL_ENTER("IsCipherAEAD");
if (n == NULL) {
WOLFSSL_MSG("bad function argumet. n is NULL.");
return 0;
}
if ((XSTRNCMP(n2,"GCM",3) == 0) || (XSTRNCMP(n3,"GCM",3) == 0) ||
(XSTRNCMP(n1,"CCM",3) == 0) ||
(XSTRNCMP(n2,"CCM",3) == 0) || (XSTRNCMP(n3,"CCM",3) == 0) ||
(XSTRNCMP(n1,"CHACHA20",8) == 0 && XSTRNCMP(n2,"POLY1305",8) == 0) ||
(XSTRNCMP(n2,"CHACHA20",8) == 0 && XSTRNCMP(n3,"POLY1305",8) == 0))
return 1;
return 0;
}
/* Returns the MAC string of a cipher or "unknown" on failure */
const char* GetCipherMacStr(char n[][MAX_SEGMENT_SZ]) {

243
src/ssl.c
View File

@ -23793,6 +23793,213 @@ int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b)
#ifdef OPENSSL_EXTRA
#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
/* return authentication NID corresponding to cipher suite
* @param cipher a pointer to WOLFSSL_CIPHER
* return NID if found, NID_undef if not found
*/
int wolfSSL_CIPHER_get_auth_nid(const WOLFSSL_CIPHER* cipher)
{
static const struct authnid {
const char* alg_name;
const int nid;
} authnid_tbl[] = {
{"RSA", NID_auth_rsa},
{"PSK", NID_auth_psk},
{"SRP", NID_auth_srp},
{"ECDSA", NID_auth_ecdsa},
{"None", NID_auth_null},
{NULL, NID_undef}
};
const struct authnid* sa;
const char* authStr;
const char* name;
char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
if ((name = GetCipherSegment(cipher, n)) == NULL) {
WOLFSSL_MSG("no suitable cipher name found");
return NID_undef;
}
authStr = GetCipherAuthStr(n);
if (authStr != NULL) {
for(sa = authnid_tbl; sa->alg_name != NULL; sa++) {
if (XSTRNCMP(sa->alg_name, authStr, XSTRLEN(sa->alg_name)) == 0) {
return sa->nid;
}
}
}
return NID_undef;
}
/* return cipher NID corresponding to cipher suite
* @param cipher a pointer to WOLFSSL_CIPHER
* return NID if found, NID_undef if not found
*/
int wolfSSL_CIPHER_get_cipher_nid(const WOLFSSL_CIPHER* cipher)
{
static const struct ciphernid {
const char* alg_name;
const int nid;
} ciphernid_tbl[] = {
{"AESGCM(256)", NID_aes_256_gcm},
{"AESGCM(128)", NID_aes_128_gcm},
{"AESCCM(128)", NID_aes_128_ccm},
{"AES(128)", NID_aes_128_cbc},
{"AES(256)", NID_aes_256_cbc},
{"CAMELLIA(256)", NID_camellia_256_cbc},
{"CAMELLIA(128)", NID_camellia_128_cbc},
{"RC4", NID_rc4},
{"3DES", NID_des_ede3_cbc},
{"CHACHA20/POLY1305(256)", NID_chacha20_poly1305},
{"None", NID_undef},
{"IDEA", NID_idea_cbc},
{"RABBIT", NID_undef},
{"HC128", NID_undef},
{NULL, NID_undef}
};
const struct ciphernid* c;
const char* encStr;
const char* name;
char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
WOLFSSL_ENTER("wolfSSL_CIPHER_get_cipher_nid");
if ((name = GetCipherSegment(cipher, n)) == NULL) {
WOLFSSL_MSG("no suitable cipher name found");
return NID_undef;
}
encStr = GetCipherEncStr(n);
if (encStr != NULL) {
for(c = ciphernid_tbl; c->alg_name != NULL; c++) {
if (XSTRNCMP(c->alg_name, encStr, XSTRLEN(c->alg_name)) == 0) {
return c->nid;
}
}
}
return NID_undef;
}
/* return digest NID corresponding to cipher suite
* @param cipher a pointer to WOLFSSL_CIPHER
* return NID if found, NID_undef if not found
*/
int wolfSSL_CIPHER_get_digest_nid(const WOLFSSL_CIPHER* cipher)
{
static const struct macnid {
const char* alg_name;
const int nid;
} macnid_tbl[] = {
{"SHA1", NID_sha1},
{"SHA256", NID_sha256},
{"SHA384", NID_sha384},
{NULL, NID_undef}
};
const struct macnid* mc;
const char* name;
const char* macStr;
char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
(void)name;
WOLFSSL_ENTER("wolfSSL_CIPHER_get_digest_nid");
if ((name = GetCipherSegment(cipher, n)) == NULL) {
WOLFSSL_MSG("no suitable cipher name found");
return NID_undef;
}
/* in MD5 case, NID will be NID_md5 */
if (XSTRSTR(name, "MD5") != NULL) {
return NID_md5;
}
macStr = GetCipherMacStr(n);
if (macStr != NULL) {
for(mc = macnid_tbl; mc->alg_name != NULL; mc++) {
if (XSTRNCMP(mc->alg_name, macStr, XSTRLEN(mc->alg_name)) == 0) {
return mc->nid;
}
}
}
return NID_undef;
}
/* return key exchange NID corresponding to cipher suite
* @param cipher a pointer to WOLFSSL_CIPHER
* return NID if found, NID_undef if not found
*/
int wolfSSL_CIPHER_get_kx_nid(const WOLFSSL_CIPHER* cipher)
{
static const struct kxnid {
const char* name;
const int nid;
} kxnid_table[] = {
{"ECDHEPSK", NID_kx_ecdhe_psk},
{"ECDH", NID_kx_ecdhe},
{"DHEPSK", NID_kx_dhe_psk},
{"DH", NID_kx_dhe},
{"RSAPSK", NID_kx_rsa_psk},
{"SRP", NID_kx_srp},
{"EDH", NID_kx_dhe},
{"RSA", NID_kx_rsa},
{NULL, NID_undef}
};
const struct kxnid* k;
const char* name;
const char* keaStr;
char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
(void)name;
WOLFSSL_ENTER("wolfSSL_CIPHER_get_kx_nid");
if ((name = GetCipherSegment(cipher, n)) == NULL) {
WOLFSSL_MSG("no suitable cipher name found");
return NID_undef;
}
/* in TLS 1.3 case, NID will be NID_kx_any */
if (XSTRNCMP(name, "TLS13", 5) == 0) {
return NID_kx_any;
}
keaStr = GetCipherKeaStr(n);
if (keaStr != NULL) {
for(k = kxnid_table; k->name != NULL; k++) {
if (XSTRNCMP(k->name, keaStr, XSTRLEN(k->name)) == 0) {
printf("k->name %s k->nid %d\n", k->name, k->nid);
return k->nid;
}
}
}
return NID_undef;
}
/* check if cipher suite is AEAD
* @param cipher a pointer to WOLFSSL_CIPHER
* return 1 if cipher is AEAD, 0 otherwise
*/
int wolfSSL_CIPHER_is_aead(const WOLFSSL_CIPHER* cipher)
{
char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
const char* name;
WOLFSSL_ENTER("wolfSSL_CIPHER_is_aead");
if ((name = GetCipherSegment(cipher, n)) == NULL) {
WOLFSSL_MSG("no suitable cipher name found");
return NID_undef;
}
return IsCipherAEAD(n);
}
/* Creates cipher->description based on cipher->offset
* cipher->offset is set in wolfSSL_get_ciphers_compat when it is added
* to a stack of ciphers.
@ -23801,8 +24008,6 @@ int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b)
*/
int wolfSSL_sk_CIPHER_description(WOLFSSL_CIPHER* cipher)
{
int ret = WOLFSSL_FAILURE;
int i,j,k;
int strLen;
unsigned long offset;
char* dp;
@ -23829,36 +24034,12 @@ int wolfSSL_sk_CIPHER_description(WOLFSSL_CIPHER* cipher)
pv.major = cipher_names[offset].major;
pv.minor = cipher_names[offset].minor;
protocol = wolfSSL_internal_get_version(&pv);
name = cipher_names[offset].name;
if (name == NULL)
return ret;
/* Segment cipher name into n[n0,n1,n2,n4]
* These are used later for comparisons to create:
* keaStr, authStr, encStr, macStr
*
* If cipher_name = ECDHE-ECDSA-AES256-SHA
* then n0 = "ECDHE", n1 = "ECDSA", n2 = "AES256", n3 = "SHA"
* and n = [n0,n1,n2,n3,0]
*/
strLen = (int)XSTRLEN(name);
for (i = 0, j = 0, k = 0; i <= strLen; i++) {
if (k >= MAX_SEGMENTS || j >= MAX_SEGMENT_SZ)
break;
if (name[i] != '-' && name[i] != '\0') {
n[k][j] = name[i]; /* Fill kth segment string until '-' */
j++;
}
else {
n[k][j] = '\0';
j = 0;
k++;
}
if ((name = GetCipherSegment(cipher, n)) == NULL) {
WOLFSSL_MSG("no suitable cipher name found");
return WOLFSSL_FAILURE;
}
/* keaStr */
keaStr = GetCipherKeaStr(n);
/* authStr */

View File

@ -47284,6 +47284,145 @@ static void test_OBJ_NAME_do_all(void)
#endif
}
static void test_SSL_CIPHER_get_xxx()
{
#if defined(OPENSSL_ALL) && !defined(NO_CERTS) && \
!defined(NO_FILESYSTEM)
printf(testingFmt, "test_SSL_CIPHER_get_xxx");
const SSL_CIPHER* cipher = NULL;
STACK_OF(SSL_CIPHER) *supportedCiphers = NULL;
int i, numCiphers = 0;
SSL_CTX* ctx = NULL;
SSL* ssl = NULL;
const char* testCertFile;
const char* testKeyFile;
char buf[256] = {0};
const char* cipher_id = NULL;
int expect_nid1 = NID_undef;
int expect_nid2 = NID_undef;
int expect_nid3 = NID_undef;
int expect_nid4 = NID_undef;
int expect_nid5 = 0;
const char* cipher_id2 = NULL;
int expect_nid21 = NID_undef;
int expect_nid22 = NID_undef;
int expect_nid23 = NID_undef;
int expect_nid24 = NID_undef;
int expect_nid25 = 0;
(void)cipher;
(void)supportedCiphers;
(void)i;
(void)numCiphers;
(void)ctx;
(void)ssl;
(void)testCertFile;
(void)testKeyFile;
#if defined(WOLFSSL_TLS13)
cipher_id = "TLS13-AES128-GCM-SHA256";
expect_nid1 = NID_auth_rsa;
expect_nid2 = NID_aes_128_gcm;
expect_nid3 = NID_sha256;
expect_nid4 = NID_kx_any;
expect_nid5 = 1;
#if !defined(WOLFSSL_NO_TLS12)
cipher_id2 = "ECDHE-RSA-AES256-GCM-SHA384";
expect_nid21 = NID_auth_rsa;
expect_nid22 = NID_aes_256_gcm;
expect_nid23 = NID_sha384;
expect_nid24 = NID_kx_ecdhe;
expect_nid25 = 1;
#endif
#endif
#ifdef NO_WOLFSSL_SERVER
AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
#else
AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
#endif
if (cipher_id) {
#ifndef NO_RSA
testCertFile = svrCertFile;
testKeyFile = svrKeyFile;
#elif defined(HAVE_ECC)
testCertFile = eccCertFile;
testKeyFile = eccKeyFile;
#else
testCertFile = NULL;
testKeyFile = NULL;
#endif
if (testCertFile != NULL && testKeyFile != NULL) {
AssertTrue(SSL_CTX_use_certificate_file(ctx, testCertFile,
SSL_FILETYPE_PEM));
AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, testKeyFile,
SSL_FILETYPE_PEM));
}
ssl = SSL_new(ctx);
AssertNotNull(ssl);
AssertIntEQ(SSL_in_init(ssl), 1);
supportedCiphers = SSL_get_ciphers(ssl);
numCiphers = sk_num(supportedCiphers);
for (i = 0; i < numCiphers; ++i) {
if ((cipher = (const WOLFSSL_CIPHER*)sk_value(supportedCiphers, i))) {
SSL_CIPHER_description(cipher, buf, sizeof(buf));
}
if (XMEMCMP(cipher_id, buf, XSTRLEN(cipher_id)) == 0) {
break;
}
}
/* test case for */
if (i != numCiphers) {
AssertIntEQ(wolfSSL_CIPHER_get_auth_nid(cipher), expect_nid1);
AssertIntEQ(wolfSSL_CIPHER_get_cipher_nid(cipher), expect_nid2);
AssertIntEQ(wolfSSL_CIPHER_get_digest_nid(cipher), expect_nid3);
AssertIntEQ(wolfSSL_CIPHER_get_kx_nid(cipher), expect_nid4);
AssertIntEQ(wolfSSL_CIPHER_is_aead(cipher), expect_nid5);
}
if (cipher_id2) {
for (i = 0; i < numCiphers; ++i) {
if ((cipher = (const WOLFSSL_CIPHER*)sk_value(supportedCiphers, i))) {
SSL_CIPHER_description(cipher, buf, sizeof(buf));
}
if (XMEMCMP(cipher_id2, buf, XSTRLEN(cipher_id2)) == 0) {
break;
}
}
/* test case for */
if (i != numCiphers) {
AssertIntEQ(wolfSSL_CIPHER_get_auth_nid(cipher), expect_nid21);
AssertIntEQ(wolfSSL_CIPHER_get_cipher_nid(cipher), expect_nid22);
AssertIntEQ(wolfSSL_CIPHER_get_digest_nid(cipher), expect_nid23);
AssertIntEQ(wolfSSL_CIPHER_get_kx_nid(cipher), expect_nid24);
AssertIntEQ(wolfSSL_CIPHER_is_aead(cipher), expect_nid25);
}
}
}
if (ctx)
SSL_CTX_free(ctx);
if(ssl)
SSL_free(ssl);
printf(resultFmt, passed);
#endif
}
/*----------------------------------------------------------------------------*
| Main
*----------------------------------------------------------------------------*/
@ -47304,6 +47443,7 @@ void ApiTest(void)
(!defined(NO_RSA) || defined(HAVE_ECC))
test_for_double_Free();
#endif
test_SSL_CIPHER_get_xxx();
test_wolfSSL_ERR_strings();
test_wolfSSL_EVP_shake128();
test_wolfSSL_EVP_shake256();

View File

@ -4877,12 +4877,15 @@ WOLFSSL_LOCAL const char* GetCipherNameInternal(const byte cipherSuite0, const b
#define MAX_SEGMENTS 5
#define MAX_SEGMENT_SZ 20
WOLFSSL_LOCAL int wolfSSL_sk_CIPHER_description(WOLFSSL_CIPHER*);
WOLFSSL_LOCAL const char* GetCipherSegment(const WOLFSSL_CIPHER* cipher,
char n[][MAX_SEGMENT_SZ]);
WOLFSSL_LOCAL const char* GetCipherProtocol(const byte minor);
WOLFSSL_LOCAL const char* GetCipherKeaStr(char n[][MAX_SEGMENT_SZ]);
WOLFSSL_LOCAL const char* GetCipherAuthStr(char n[][MAX_SEGMENT_SZ]);
WOLFSSL_LOCAL const char* GetCipherEncStr(char n[][MAX_SEGMENT_SZ]);
WOLFSSL_LOCAL const char* GetCipherMacStr(char n[][MAX_SEGMENT_SZ]);
WOLFSSL_LOCAL int SetCipherBits(const char* enc);
WOLFSSL_LOCAL int IsCipherAEAD(char n[][MAX_SEGMENT_SZ]);
#endif
WOLFSSL_LOCAL const char* GetCipherNameIana(const byte cipherSuite0, const byte cipherSuite);
WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl);

View File

@ -254,6 +254,7 @@ enum {
NID_hmac = 855,
NID_cmac = 894,
NID_dhKeyAgreement= 28,
NID_rc4 = 5,
EVP_PKEY_DH = NID_dhKeyAgreement,
EVP_PKEY_HMAC = NID_hmac,
AES_128_CFB1_TYPE = 24,
@ -304,6 +305,8 @@ enum {
NID_aes_128_cbc = 419,
NID_aes_192_cbc = 423,
NID_aes_256_cbc = 427,
NID_aes_128_ccm = 896,
NID_aes_256_ccm = 902,
NID_aes_128_gcm = 895,
NID_aes_192_gcm = 898,
NID_aes_256_gcm = 901,
@ -331,7 +334,34 @@ enum {
NID_aes_192_ofb = 424,
NID_aes_256_ofb = 428,
NID_aes_128_xts = 913,
NID_aes_256_xts = 914
NID_aes_256_xts = 914,
NID_camellia_128_cbc = 751,
NID_camellia_256_cbc = 753,
NID_chacha20_poly1305 = 1018
};
enum {
/* key exchange */
NID_kx_rsa = 1037,
NID_kx_ecdhe = 1038,
NID_kx_dhe = 1039,
NID_kx_ecdhe_psk= 1040,
NID_kx_dhe_psk = 1041,
NID_kx_rsa_psk= 1042,
NID_kx_psk = 1043,
NID_kx_srp = 1044,
NID_kx_gost = 1045,
NID_kx_any = 1063,
/* server authentication */
NID_auth_rsa = 1046,
NID_auth_ecdsa = 1047,
NID_auth_psk = 1048,
NID_auth_dss = 1049,
NID_auth_srp = 1052,
NID_auth_null = 1054,
NID_auth_any = 1055
};
#define NID_X9_62_id_ecPublicKey EVP_PKEY_EC

View File

@ -361,6 +361,11 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS;
#define SSL_CIPHER_get_id wolfSSL_CIPHER_get_id
#define SSL_CIPHER_get_rfc_name wolfSSL_CIPHER_get_name
#define SSL_CIPHER_standard_name wolfSSL_CIPHER_get_name
#define SSL_CIPHER_get_auth_nid wolfSSL_CIPHER_get_auth_nid
#define SSL_CIPHER_get_cipher_nid wolfSSL_CIPHER_get_cipher_nid
#define SSL_CIPHER_get_digest_nid wolfSSL_CIPHER_get_digest_nid
#define SSL_CIPHER_get_kx_nid wolfSSL_CIPHER_get_kx_nid
#define SSL_CIPHER_is_aead wolfSSL_CIPHER_is_aead
#define SSL_get_cipher_by_value wolfSSL_get_cipher_by_value
#define SSL_get1_session wolfSSL_get1_session

View File

@ -1403,6 +1403,11 @@ WOLFSSL_API char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER*, char*, int);
WOLFSSL_API const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher);
WOLFSSL_API const char* wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher);
WOLFSSL_API word32 wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher);
WOLFSSL_API int wolfSSL_CIPHER_get_auth_nid(const WOLFSSL_CIPHER* cipher);
WOLFSSL_API int wolfSSL_CIPHER_get_cipher_nid(const WOLFSSL_CIPHER* cipher);
WOLFSSL_API int wolfSSL_CIPHER_get_digest_nid(const WOLFSSL_CIPHER* cipher);
WOLFSSL_API int wolfSSL_CIPHER_get_kx_nid(const WOLFSSL_CIPHER* cipher);
WOLFSSL_API int wolfSSL_CIPHER_is_aead(const WOLFSSL_CIPHER* cipher);
WOLFSSL_API const WOLFSSL_CIPHER* wolfSSL_get_cipher_by_value(word16 value);
WOLFSSL_API const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session);
WOLFSSL_API const char* wolfSSL_get_cipher(WOLFSSL*);