Refactor of public key cert check

Reafctored public key check from libtasn_read_cert_pk_parameters()
into its own function libtasn_cert_pk_oid(). The make use of it
instead of gnutls_x509_crt_get_pk_oid().
This commit is contained in:
Henrik Andersson 2019-01-23 16:18:41 +01:00
parent e33b9b7ea6
commit 78a9dcff68
3 changed files with 53 additions and 39 deletions

57
asn.c
View File

@ -207,7 +207,42 @@ int write_pkcs1_der_pubkey(const gnutls_datum_t *m, const gnutls_datum_t *e, uin
return 0;
}
int libtasn_read_cert_pk_parameters(uint8_t *data, size_t len, gnutls_datum_t *m, gnutls_datum_t *e, int check_pk_algo)
int libtasn_read_cert_pk_oid(uint8_t *data, size_t len, char *oid, size_t *oid_size)
{
int asn1_rv;
asn1_node asn_cert;
/* Parse DER encoded x.509 certificate */
if (!asn_defs) {
if (init_asn1_lib() != 0) {
return 1;
}
}
if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.Certificate", &asn_cert))) {
logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element. Error = 0x%x (%s)\n",
__FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
return 1;
}
if (ASN1_SUCCESS != (asn1_rv = asn1_der_decoding(&asn_cert, data, len, errstr))) {
logger(Core, Error, "%s:%s:%d Failed to decode certificate object. Error = 0x%x (%s)\n",
__FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
return 1;
}
if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_cert, "tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm",
oid, (int *)oid_size)))
{
logger(Core, Error, "%s:%s:%d Failed to get cert's public key algorithm. Error = 0x%x (%s)\n",
__FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
return 1;
}
return 0;
}
int libtasn_read_cert_pk_parameters(uint8_t *data, size_t len, gnutls_datum_t *m, gnutls_datum_t *e)
{
int asn1_rv;
asn1_node asn_cert;
@ -234,26 +269,6 @@ int libtasn_read_cert_pk_parameters(uint8_t *data, size_t len, gnutls_datum_t *m
return 1;
}
if (check_pk_algo) {
/* Get and check cert's public key algorithm */
buflen = sizeof(buf) - 1;
if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_cert, "tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm", buf, (int *)&buflen))) {
logger(Core, Error, "%s:%s:%d Failed to get cert's public key algorithm. Error = 0x%x (%s)\n",
__FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
return 1;
}
if ((strncmp((char *)buf, OID_SHA_WITH_RSA_SIGNATURE, strlen(OID_SHA_WITH_RSA_SIGNATURE)) != 0)
&& (strncmp((char *)buf, OID_MD5_WITH_RSA_SIGNATURE, strlen(OID_MD5_WITH_RSA_SIGNATURE)) != 0)) {
logger(Core, Error, "%s:%s:%d Wrong public key algorithm: %s\n",
__FILE__, __func__, __LINE__, buf);
return 1;
}
}
buflen = sizeof(buf) - 1;
if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_cert, "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey", buf, &buflen))) {
logger(Core, Error, "%s:%s:%d Failed to get cert's public key. Error = 0x%x (%s)\n",

4
asn.h
View File

@ -34,7 +34,9 @@ extern "C" {
int init_asn1_lib(void);
int write_pkcs1_der_pubkey(const gnutls_datum_t *m, const gnutls_datum_t *e, uint8_t *out, int *out_len);
int libtasn_read_cert_pk_parameters(uint8_t *data, size_t len, gnutls_datum_t *m, gnutls_datum_t *e, int check_pk_algo);
int libtasn_read_cert_pk_oid(uint8_t *data, size_t len, char *oid, size_t *oid_size);
int libtasn_read_cert_pk_parameters(uint8_t *data, size_t len, gnutls_datum_t *m, gnutls_datum_t *e);
#ifdef __cplusplus
}

31
ssl.c
View File

@ -212,17 +212,22 @@ rdssl_cert_to_rkey(RDSSL_CERT * cert, uint32 * key_len)
} else if (algo == GNUTLS_E_UNIMPLEMENTED_FEATURE) {
/* Maybe we should get rid of gnutls_x509_crt_get_pk_oid() and
check public key algo in libtasn_read_cert_pk_params() */
#if GNUTLS_VERSION_NUMBER >= 0x030500
// manpage says that this function is useful when gnutls_x509_crt_get_pk_algorithm() returns GNUTLS_PK_UNKNOWN
if ((ret = gnutls_x509_crt_get_pk_oid(*cert, oid, &oid_size)) != GNUTLS_E_SUCCESS) {
logger(Protocol, Error, "%s:%s:%d: Failed to get OID of public key algorithm. GnuTLS error = 0x%02x (%s)\n",
len = sizeof(data);
if ((ret = gnutls_x509_crt_export(*cert, GNUTLS_X509_FMT_DER, data, &len)) != GNUTLS_E_SUCCESS) {
logger(Protocol, Error, "%s:%s:%d: Failed to encode X.509 certificate to DER. GnuTLS error = 0x%02x (%s)\n",
__FILE__, __func__, __LINE__, ret, gnutls_strerror(ret));
return NULL;
}
/* Validate public key algorithm as OID_SHA_WITH_RSA_SIGNATURE
or OID_MD5_WITH_RSA_SIGNATURE
*/
if ((ret = libtasn_read_cert_pk_oid(data, len, oid, &oid_size)) != 0) {
logger(Protocol, Error, "%s:%s:%d: Failed to get OID of public key algorithm.\n",
__FILE__, __func__, __LINE__);
return NULL;
}
if (!strncmp(oid, OID_SHA_WITH_RSA_SIGNATURE, strlen(OID_SHA_WITH_RSA_SIGNATURE))
|| !strncmp(oid, OID_MD5_WITH_RSA_SIGNATURE, strlen(OID_MD5_WITH_RSA_SIGNATURE))) {
check_pk_algo = 0;
@ -231,17 +236,9 @@ rdssl_cert_to_rkey(RDSSL_CERT * cert, uint32 * key_len)
__FILE__, __func__, __LINE__, algo, oid);
return NULL;
}
#endif
len = sizeof(data);
if ((ret = gnutls_x509_crt_export(*cert, GNUTLS_X509_FMT_DER, data, &len)) != GNUTLS_E_SUCCESS) {
logger(Protocol, Error, "%s:%s:%d: Failed to encode X.509 certificate to DER. GnuTLS error = 0x%02x (%s)\n",
__FILE__, __func__, __LINE__, ret, gnutls_strerror(ret));
return NULL;
}
if ((ret = libtasn_read_cert_pk_parameters(data, len, &m, &e, check_pk_algo)) != 0) {
/* Get public key parameters */
if ((ret = libtasn_read_cert_pk_parameters(data, len, &m, &e)) != 0) {
logger(Protocol, Error, "%s:%s:%d: Failed to read RSA public key parameters\n",
__FILE__, __func__, __LINE__);