RPK: Define Certificates correctly for (D)TLS1.2

As per https://datatracker.ietf.org/doc/html/rfc7250#section-3 Figure 1,
the RPK is a single ASN.1_subjectPublicKeyInfo, whereas X509 certificates
etc. are transmitted as a certificate list (even if there is only 1).

This is for (D)TLS1.2 transfers, and this PR fixes this.

As per https://datatracker.ietf.org/doc/html/rfc8446#section-4.4.2 all
certificates (both RPK and Z509) are transferred using a certificate list.

Update examples client to support RPK certificates.

For testing:-
Server:
$ gnutls-serv --http --x509fmtder --priority NORMAL:+CTYPE-CLI-RAWPK:+CTYPE-SRV-RAWPK --rawpkfile certs/server-keyPub.der --rawpkkeyfile certs/server-key.der

Client:
$ examples/client/client -g -p 5556 -c certs/client-keyPub.der -k certs/client-key.der --rpk --files-are-der
This commit is contained in:
Jon Shallow
2024-03-20 14:49:59 +00:00
parent 8970ff4c34
commit f2e6f49721
2 changed files with 116 additions and 21 deletions

View File

@ -1103,7 +1103,7 @@ static int ClientWriteRead(WOLFSSL* ssl, const char* msg, int msgSz,
/* 4. add the same message into Japanese section */
/* (will be translated later) */
/* 5. add printf() into suitable position of Usage() */
static const char* client_usage_msg[][75] = {
static const char* client_usage_msg[][78] = {
/* English */
{
" NOTE: All files relative to wolfSSL home dir\n", /* 0 */
@ -1318,9 +1318,13 @@ static const char* client_usage_msg[][75] = {
#ifndef NO_PSK
"--openssl-psk Use TLS 1.3 PSK callback compatible with OpenSSL\n", /* 74 */
#endif
#ifdef HAVE_RPK
"--rpk Use RPK for the defined certificates\n", /* 75 */
#endif
"--files-are-der Specified files are in DER, not PEM format\n", /* 76 */
"\n"
"For simpler wolfSSL TLS client examples, visit\n"
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 75 */
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 77 */
NULL,
},
#ifndef NO_MULTIBYTE_PRINT
@ -1542,10 +1546,14 @@ static const char* client_usage_msg[][75] = {
#ifndef NO_PSK
"--openssl-psk Use TLS 1.3 PSK callback compatible with OpenSSL\n", /* 74 */
#endif
#ifdef HAVE_RPK
"--rpk Use RPK for the defined certificates\n", /* 75 */
#endif
"--files-are-der Specified files are in DER, not PEM format\n", /* 76 */
"\n"
"より簡単なwolfSSL TLS クライアントの例については"
"下記にアクセスしてください\n"
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 75 */
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 77 */
NULL,
},
#endif
@ -1763,9 +1771,9 @@ static void Usage(void)
printf("%s", msg[++msgid]); /* Examples repo link */
#ifdef HAVE_PQC
printf("%s", msg[++msgid]); /* --pqc */
printf("%s", msg[++msgid]); /* --pqc options */
printf("%s", msg[++msgid]); /* more --pqc options */
printf("%s", msg[++msgid]); /* more --pqc options */
#endif
#ifdef WOLFSSL_SRTP
printf("%s", msg[++msgid]); /* dtls-srtp */
#endif
#ifdef WOLFSSL_SYS_CA_CERTS
printf("%s", msg[++msgid]); /* --sys-ca-certs */
@ -1773,9 +1781,14 @@ static void Usage(void)
#ifdef HAVE_SUPPORTED_CURVES
printf("%s", msg[++msgid]); /* --onlyPskDheKe */
#endif
#ifdef WOLFSSL_SRTP
printf("%s", msg[++msgid]); /* dtls-srtp */
#ifndef NO_PSK
printf("%s", msg[++msgid]); /* --openssl-psk */
#endif
#ifdef HAVE_RPK
printf("%s", msg[++msgid]); /* --rpk */
#endif
printf("%s", msg[++msgid]); /* --files-are-der */
printf("%s", msg[++msgid]); /* Documentation Hint */
}
#ifdef WOLFSSL_SRTP
@ -1919,6 +1932,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
{ "openssl-psk", 0, 265 },
#endif
{ "quieter", 0, 266 },
#ifdef HAVE_RPK
{ "rpk", 0, 267 },
#endif /* HAVE_RPK */
{ "files-are-der", 0, 268 },
{ 0, 0, 0 }
};
#endif
@ -2059,6 +2076,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
int useDtlsCID = 0;
char dtlsCID[DTLS_CID_BUFFER_SIZE] = { 0 };
#endif /* WOLFSSL_DTLS_CID */
#ifdef HAVE_RPK
int useRPK = 0;
#endif /* HAVE_RPK */
int fileFormat = WOLFSSL_FILETYPE_PEM;
char buffer[WOLFSSL_MAX_ERROR_SZ];
@ -2756,6 +2777,14 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
case 266:
quieter = 1;
break;
case 267:
#ifdef HAVE_RPK
useRPK = 1;
#endif /* HAVE_RPK */
break;
case 268:
fileFormat = WOLFSSL_FILETYPE_ASN1;
break;
default:
Usage();
XEXIT_T(MY_EX_USAGE);
@ -3129,6 +3158,21 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
}
#endif
#ifdef HAVE_RPK
if (useRPK) {
char ctype[] = {WOLFSSL_CERT_TYPE_RPK};
char stype[] = {WOLFSSL_CERT_TYPE_RPK};
wolfSSL_CTX_set_client_cert_type(ctx, ctype, sizeof(ctype)/sizeof(ctype[0]));
wolfSSL_CTX_set_server_cert_type(ctx, stype, sizeof(stype)/sizeof(stype[0]));
usePsk = 0;
#ifdef HAVE_CRL
disableCRL = 1;
#endif
doPeerCheck = 0;
}
#endif /* HAVE_RPK */
if (usePsk) {
#ifndef NO_PSK
const char *defaultCipherList = cipherList;
@ -3261,7 +3305,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS)
err_sys("can't load client cert buffer");
#elif !defined(TEST_LOAD_BUFFER)
if (wolfSSL_CTX_use_certificate_chain_file(ctx, ourCert)
if (wolfSSL_CTX_use_certificate_chain_file_format(ctx, ourCert, fileFormat)
!= WOLFSSL_SUCCESS) {
wolfSSL_CTX_free(ctx); ctx = NULL;
err_sys("can't load client cert file, check file and run from"
@ -3285,7 +3329,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
sizeof_client_key_der_2048, SSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS)
err_sys("can't load client private key buffer");
#elif !defined(TEST_LOAD_BUFFER)
if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, WOLFSSL_FILETYPE_PEM)
if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, fileFormat)
!= WOLFSSL_SUCCESS) {
wolfSSL_CTX_free(ctx); ctx = NULL;
err_sys("can't load client private key file, check file and run "
@ -3593,7 +3637,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
err_sys("can't load client cert buffer");
}
#elif !defined(TEST_LOAD_BUFFER)
if (wolfSSL_use_certificate_chain_file(ssl, ourCert)
if (wolfSSL_use_certificate_chain_file_format(ssl, ourCert, fileFormat)
!= WOLFSSL_SUCCESS) {
wolfSSL_CTX_free(ctx); ctx = NULL;
err_sys("can't load client cert file, check file and run from"
@ -3614,7 +3658,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
sizeof_client_key_der_2048, SSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS)
err_sys("can't load client private key buffer");
#elif !defined(TEST_LOAD_BUFFER)
if (wolfSSL_use_PrivateKey_file(ssl, ourKey, WOLFSSL_FILETYPE_PEM)
if (wolfSSL_use_PrivateKey_file(ssl, ourKey, fileFormat)
!= WOLFSSL_SUCCESS) {
wolfSSL_CTX_free(ctx); ctx = NULL;
err_sys("can't load client private key file, check file and run "

View File

@ -14288,7 +14288,25 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ERROR_OUT(BUFFER_ERROR, exit_ppc);
}
c24to32(input + args->idx, &listSz);
args->idx += OPAQUE24_LEN;
#ifdef HAVE_RPK
/*
* If this is RPK from the peer, then single cert (if TLS1.2).
* So, ListSz location is same as CertSz location, so fake
* we have just seen this ListSz.
*/
if (!IsAtLeastTLSv1_3(ssl->version) &&
((ssl->options.side == WOLFSSL_SERVER_END &&
ssl->options.rpkState.received_ClientCertTypeCnt == 1 &&
ssl->options.rpkState.received_ClientCertTypes[0] == WOLFSSL_CERT_TYPE_RPK) ||
(ssl->options.side == WOLFSSL_CLIENT_END &&
ssl->options.rpkState.received_ServerCertTypeCnt == 1 &&
ssl->options.rpkState.received_ServerCertTypes[0] == WOLFSSL_CERT_TYPE_RPK))) {
listSz += OPAQUE24_LEN;
} else
#endif /* HAVE_RPK */
{
args->idx += OPAQUE24_LEN;
}
if (listSz > MAX_CERTIFICATE_SZ) {
ERROR_OUT(BUFFER_ERROR, exit_ppc);
}
@ -23076,6 +23094,9 @@ int SendCertificate(WOLFSSL* ssl)
int ret = 0;
word32 certSz, certChainSz, headerSz, listSz, payloadSz;
word32 length, maxFragment;
#ifdef HAVE_RPK
int usingRpkTls12 = 0;
#endif /* HAVE_RPK */
WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND);
WOLFSSL_ENTER("SendCertificate");
@ -23085,6 +23106,21 @@ int SendCertificate(WOLFSSL* ssl)
return 0; /* not needed */
}
#ifdef HAVE_RPK
if (!IsAtLeastTLSv1_3(ssl->version)) {
/* If this is (D)TLS1.2 and RPK, then single cert, not list. */
if (ssl->options.side == WOLFSSL_SERVER_END) {
if (ssl->options.rpkState.sending_ServerCertTypeCnt == 1 &&
ssl->options.rpkState.sending_ServerCertTypes[0] == WOLFSSL_CERT_TYPE_RPK)
usingRpkTls12 = 1;
} else if (ssl->options.side == WOLFSSL_CLIENT_END) {
if (ssl->options.rpkState.sending_ClientCertTypeCnt == 1 &&
ssl->options.rpkState.sending_ClientCertTypes[0] == WOLFSSL_CERT_TYPE_RPK)
usingRpkTls12 = 1;
}
}
#endif /* HAVE_RPK */
if (ssl->options.sendVerify == SEND_BLANK_CERT) {
#ifdef OPENSSL_EXTRA
if (ssl->version.major == SSLv3_MAJOR
@ -23107,10 +23143,19 @@ int SendCertificate(WOLFSSL* ssl)
return BUFFER_ERROR;
}
certSz = ssl->buffers.certificate->length;
headerSz = 2 * CERT_HEADER_SZ;
#ifdef HAVE_RPK
if (usingRpkTls12) {
headerSz = 1 * CERT_HEADER_SZ;
listSz = certSz;
} else {
#endif /* HAVE_RPK */
headerSz = 2 * CERT_HEADER_SZ;
listSz = certSz + CERT_HEADER_SZ;
#ifdef HAVE_RPK
}
#endif /* HAVE_RPK */
/* list + cert size */
length = certSz + headerSz;
listSz = certSz + CERT_HEADER_SZ;
/* may need to send rest of chain, already has leading size(s) */
if (certSz && ssl->buffers.certChain) {
@ -23203,12 +23248,18 @@ int SendCertificate(WOLFSSL* ssl)
}
/* list total */
c32to24(listSz, output + i);
if (ssl->options.dtls || !IsEncryptionOn(ssl, 1))
HashRaw(ssl, output + i, CERT_HEADER_SZ);
i += CERT_HEADER_SZ;
length -= CERT_HEADER_SZ;
fragSz -= CERT_HEADER_SZ;
#ifdef HAVE_RPK
if (!usingRpkTls12) {
#endif /* HAVE_RPK */
c32to24(listSz, output + i);
if (ssl->options.dtls || !IsEncryptionOn(ssl, 1))
HashRaw(ssl, output + i, CERT_HEADER_SZ);
i += CERT_HEADER_SZ;
length -= CERT_HEADER_SZ;
fragSz -= CERT_HEADER_SZ;
#ifdef HAVE_RPK
}
#endif /* HAVE_RPK */
if (certSz) {
c32to24(certSz, output + i);
if (ssl->options.dtls || !IsEncryptionOn(ssl, 1))