summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2017-07-27 16:53:57 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2017-08-03 11:57:52 +0200
commit4256ef71a7842830f7a27061c31c36554a6b97cc (patch)
tree0ed46372269b378c67093afe6eaa8fbb046f02f4
parent86da29a32b34bd2f84f914f5749c260d9ff11add (diff)
downloadgnutls-4256ef71a7842830f7a27061c31c36554a6b97cc.tar.gz
Added convention for missing SubjectPublicKeyInfo params field
That is, when that field is missing, the spki_st structure field pk will be set to GNUTLS_PK_UNKNOWN. In that case other fields are undefined. Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r--lib/crypto-backend.h4
-rw-r--r--lib/includes/gnutls/abstract.h4
-rw-r--r--lib/privkey.c22
-rw-r--r--lib/pubkey.c3
-rw-r--r--lib/x509/crq.c3
-rw-r--r--lib/x509/key_decode.c10
-rw-r--r--lib/x509/key_encode.c3
-rw-r--r--lib/x509/mpi.c32
-rw-r--r--lib/x509/privkey.c23
-rw-r--r--lib/x509/privkey_pkcs8.c6
-rw-r--r--lib/x509/sign.c2
-rw-r--r--lib/x509/x509.c4
-rw-r--r--lib/x509/x509_int.h11
13 files changed, 83 insertions, 44 deletions
diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h
index 347d6a7806..0f8b93eab4 100644
--- a/lib/crypto-backend.h
+++ b/lib/crypto-backend.h
@@ -163,7 +163,9 @@ typedef struct gnutls_crypto_bigint {
gnutls_bigint_format_t format);
} gnutls_crypto_bigint_st;
-/* additional information about the public key
+/* Additional information about the public key, filled from
+ * SubjectPublicKeyInfo parameters. When there are no parameters,
+ * the pk field will be set to GNUTLS_PK_UNKNOWN.
*/
typedef struct gnutls_x509_spki_st {
/* We can have a key which is of type RSA, but a certificate
diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h
index 482101b519..ab4d7019c2 100644
--- a/lib/includes/gnutls/abstract.h
+++ b/lib/includes/gnutls/abstract.h
@@ -321,6 +321,7 @@ int gnutls_privkey_status(gnutls_privkey_t key);
* @GNUTLS_PRIVKEY_DISABLE_CALLBACKS: The following flag disables call to PIN callbacks etc.
* Only relevant to TPM keys.
* @GNUTLS_PRIVKEY_FLAG_PROVABLE: When generating a key involving prime numbers, use provable primes; a seed may be required.
+ * @GNUTLS_PRIVKEY_FLAG_CA: The generated private key is going to be used as a CA (relevant for RSA-PSS keys).
* @GNUTLS_PRIVKEY_FLAG_EXPORT_COMPAT: Keys generated or imported as provable require an extended format which cannot be read by previous versions
* of gnutls or other applications. By setting this flag the key will be exported in a backwards compatible way,
* even if the information about the seed used will be lost.
@@ -335,7 +336,8 @@ typedef enum gnutls_privkey_flags {
GNUTLS_PRIVKEY_FLAG_PROVABLE = 1 << 5,
GNUTLS_PRIVKEY_FLAG_EXPORT_COMPAT = 1 << 6,
GNUTLS_PRIVKEY_SIGN_FLAG_RSA_PSS = 1 << 7,
- GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE = 1 << 8
+ GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE = 1 << 8,
+ GNUTLS_PRIVKEY_FLAG_CA = 1 << 9
} gnutls_privkey_flags_t;
int gnutls_privkey_import_pkcs11(gnutls_privkey_t pkey,
diff --git a/lib/privkey.c b/lib/privkey.c
index cd85010346..91ec22479d 100644
--- a/lib/privkey.c
+++ b/lib/privkey.c
@@ -285,8 +285,8 @@ _gnutls_privkey_get_spki_params(gnutls_privkey_t key,
case GNUTLS_PRIVKEY_EXT:
break;
case GNUTLS_PRIVKEY_X509:
- return _gnutls_x509_privkey_get_spki_params(key->key.x509,
- params);
+ _gnutls_x509_privkey_get_spki_params(key->key.x509, params);
+ return 0;
default:
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
@@ -299,7 +299,11 @@ _gnutls_privkey_get_spki_params(gnutls_privkey_t key,
/* This function fills in PARAMS with the necessary parameters to sign
* with PK and DIG. PARAMS must be initialized with
- * _gnutls_privkey_get_spki_params in advance. */
+ * _gnutls_privkey_get_spki_params in advance.
+ *
+ * After calling this function the params structure will
+ * be initialized even if the original SubjectPublicKeyInfo was empty.
+ */
int
_gnutls_privkey_update_spki_params(gnutls_privkey_t key,
gnutls_pk_algorithm_t pk,
@@ -318,8 +322,8 @@ _gnutls_privkey_update_spki_params(gnutls_privkey_t key,
}
key_pk = gnutls_privkey_get_pk_algorithm(key, &bits);
- if (!(key_pk == pk ||
- (key_pk == GNUTLS_PK_RSA && pk == GNUTLS_PK_RSA_PSS))) {
+ if ((key_pk != pk) &&
+ !(key_pk == GNUTLS_PK_RSA && pk == GNUTLS_PK_RSA_PSS)) {
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
@@ -334,7 +338,7 @@ _gnutls_privkey_update_spki_params(gnutls_privkey_t key,
if (params->pk == GNUTLS_PK_RSA)
salt_size = 0;
else if (params->pk == GNUTLS_PK_RSA_PSS) {
- if (dig != params->rsa_pss_dig) {
+ if (params->rsa_pss_dig != GNUTLS_DIG_UNKNOWN && dig != params->rsa_pss_dig) {
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
@@ -349,7 +353,6 @@ _gnutls_privkey_update_spki_params(gnutls_privkey_t key,
params->rsa_pss_dig = dig;
}
-
params->pk = pk;
return 0;
@@ -987,7 +990,7 @@ gnutls_privkey_sign_data(gnutls_privkey_t signer,
}
ret = _gnutls_privkey_update_spki_params(signer, signer->pk_algorithm,
- hash, flags, &params);
+ hash, flags, &params);
if (ret < 0) {
gnutls_assert();
return ret;
@@ -1633,6 +1636,9 @@ gnutls_privkey_get_spki(gnutls_privkey_t privkey, gnutls_x509_spki_t spki, unsig
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
+ if (privkey->key.x509->params.spki.pk == GNUTLS_PK_UNKNOWN)
+ return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+
memcpy(spki, &privkey->key.x509->params.spki, sizeof(gnutls_x509_spki_st));
return 0;
diff --git a/lib/pubkey.c b/lib/pubkey.c
index 9cbdd25fbb..1ae8c05830 100644
--- a/lib/pubkey.c
+++ b/lib/pubkey.c
@@ -2152,6 +2152,9 @@ gnutls_pubkey_get_spki(gnutls_pubkey_t pubkey, gnutls_x509_spki_t spki, unsigned
return GNUTLS_E_INVALID_REQUEST;
}
+ if (pubkey->params.spki.pk == GNUTLS_PK_UNKNOWN)
+ return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+
memcpy(spki, &pubkey->params.spki, sizeof(gnutls_x509_spki_st));
return 0;
diff --git a/lib/x509/crq.c b/lib/x509/crq.c
index f3b50923b5..6088ef9ac6 100644
--- a/lib/x509/crq.c
+++ b/lib/x509/crq.c
@@ -1332,6 +1332,9 @@ gnutls_x509_crq_get_spki(gnutls_x509_crq_t crq,
return result;
}
+ if (params.pk == GNUTLS_PK_UNKNOWN)
+ return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+
spki->rsa_pss_dig = params.rsa_pss_dig;
spki->salt_size = params.salt_size;
diff --git a/lib/x509/key_decode.c b/lib/x509/key_decode.c
index 97f240e783..6f5f9eadb5 100644
--- a/lib/x509/key_decode.c
+++ b/lib/x509/key_decode.c
@@ -450,10 +450,16 @@ int _gnutls_x509_check_pubkey_params(gnutls_pk_algorithm_t algo,
{
switch (algo) {
case GNUTLS_PK_RSA_PSS: {
- unsigned bits = pubkey_to_bits(params);
- const mac_entry_st *me = hash_to_entry(params->spki.rsa_pss_dig);
+ unsigned bits;
+ const mac_entry_st *me;
size_t hash_size;
+ if (params->spki.pk == GNUTLS_PK_UNKNOWN) /* no params present */
+ return 0;
+
+ bits = pubkey_to_bits(params);
+
+ me = hash_to_entry(params->spki.rsa_pss_dig);
if (unlikely(me == NULL))
return gnutls_assert_val(GNUTLS_E_CERTIFICATE_ERROR);
diff --git a/lib/x509/key_encode.c b/lib/x509/key_encode.c
index 24e7750536..77923a130d 100644
--- a/lib/x509/key_encode.c
+++ b/lib/x509/key_encode.c
@@ -334,6 +334,9 @@ _gnutls_x509_write_rsa_pss_params(gnutls_x509_spki_st *params,
der->data = NULL;
der->size = 0;
+ if (params->pk != GNUTLS_PK_RSA_PSS)
+ return 0;
+
if ((result = asn1_create_element
(_gnutls_get_gnutls_asn(), "GNUTLS.RSAPSSParameters", &spk))
!= ASN1_SUCCESS) {
diff --git a/lib/x509/mpi.c b/lib/x509/mpi.c
index 4574deead8..c6a240dff3 100644
--- a/lib/x509/mpi.c
+++ b/lib/x509/mpi.c
@@ -141,6 +141,10 @@ _gnutls_get_asn_mpis(ASN1_TYPE asn, const char *root,
if (pk_algorithm != GNUTLS_PK_RSA && pk_algorithm != GNUTLS_PK_EDDSA_ED25519 && pk_algorithm != GNUTLS_PK_ECDH_X25519) {
/* RSA and EdDSA do not use parameters */
result = _gnutls_x509_read_value(asn, name, &tmp);
+ if (pk_algorithm == GNUTLS_PK_RSA_PSS &&
+ (result == GNUTLS_E_ASN1_VALUE_NOT_FOUND || result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)) {
+ goto skip_params;
+ }
if (result < 0) {
gnutls_assert();
goto error;
@@ -158,6 +162,7 @@ _gnutls_get_asn_mpis(ASN1_TYPE asn, const char *root,
_gnutls_free_datum(&tmp);
}
+ skip_params:
/* Now read the public key */
_asnstr_append_name(name, sizeof(name), root, ".subjectPublicKey");
@@ -220,8 +225,8 @@ _gnutls_x509_crq_get_mpis(gnutls_x509_crq_t cert,
* This is the "signatureAlgorithm" fields.
*/
int
-_gnutls_x509_read_sign_params(ASN1_TYPE src, const char *src_name,
- gnutls_x509_spki_st *params)
+_gnutls_x509_read_pkalgo_params(ASN1_TYPE src, const char *src_name,
+ gnutls_x509_spki_st *params, unsigned is_sig)
{
int result;
char name[128];
@@ -246,10 +251,16 @@ _gnutls_x509_read_sign_params(ASN1_TYPE src, const char *src_name,
_gnutls_str_cat(name, sizeof(name), ".parameters");
result = _gnutls_x509_read_value(src, name, &tmp);
- if (result < 0 &&
- result != GNUTLS_E_ASN1_ELEMENT_NOT_FOUND &&
- result != GNUTLS_E_ASN1_VALUE_NOT_FOUND) {
- _gnutls_free_datum(&tmp);
+ if (result < 0) {
+ if (!is_sig) {
+ if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND ||
+ result != GNUTLS_E_ASN1_VALUE_NOT_FOUND) {
+ /* it is ok to not have parameters in SPKI, but
+ * not in signatures */
+ return 0;
+ }
+ }
+
return gnutls_assert_val(result);
}
@@ -261,15 +272,6 @@ _gnutls_x509_read_sign_params(ASN1_TYPE src, const char *src_name,
gnutls_assert();
return result;
- } else {
- const gnutls_sign_entry_st *se;
-
- memset(params, 0, sizeof(gnutls_x509_spki_st));
-
- se = _gnutls_oid_to_sign_entry(oid);
- if (se != NULL) {
- params->pk = se->pk;
- }
}
return 0;
diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c
index 7a6904a5cf..7b8423c47e 100644
--- a/lib/x509/privkey.c
+++ b/lib/x509/privkey.c
@@ -1243,6 +1243,13 @@ gnutls_x509_privkey_get_pk_algorithm2(gnutls_x509_privkey_t key,
return key->params.algo;
}
+void
+_gnutls_x509_privkey_get_spki_params(gnutls_x509_privkey_t key,
+ gnutls_x509_spki_st *params)
+{
+ memcpy(params, &key->params.spki, sizeof(gnutls_x509_spki_st));
+}
+
/**
* gnutls_x509_privkey_get_spki:
* @key: should contain a #gnutls_x509_privkey_t type
@@ -1262,7 +1269,10 @@ gnutls_x509_privkey_get_spki(gnutls_x509_privkey_t key, gnutls_x509_spki_t spki,
return GNUTLS_E_INVALID_REQUEST;
}
- memcpy(spki, &key->params.spki, sizeof (gnutls_x509_spki_st));
+ if (key->params.spki.pk == GNUTLS_PK_UNKNOWN)
+ return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+
+ _gnutls_x509_privkey_get_spki_params(key, spki);
return 0;
}
@@ -1650,7 +1660,7 @@ gnutls_x509_privkey_generate2(gnutls_x509_privkey_t key,
return ret;
}
- if (algo == GNUTLS_PK_RSA_PSS) {
+ if (algo == GNUTLS_PK_RSA_PSS && (flags & GNUTLS_PRIVKEY_FLAG_CA)) {
const mac_entry_st *me;
key->params.spki.pk = GNUTLS_PK_RSA_PSS;
@@ -2181,12 +2191,3 @@ void gnutls_x509_privkey_set_flags(gnutls_x509_privkey_t key,
key->flags |= flags;
}
-int
-_gnutls_x509_privkey_get_spki_params(gnutls_x509_privkey_t key,
- gnutls_x509_spki_st *params)
-{
- memcpy(params, &key->params.spki, sizeof(gnutls_x509_spki_st));
- params->pk = key->params.algo;
- return 0;
-}
-
diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c
index 7042cca997..b8d9b80a7f 100644
--- a/lib/x509/privkey_pkcs8.c
+++ b/lib/x509/privkey_pkcs8.c
@@ -958,9 +958,14 @@ _decode_pkcs8_rsa_pss_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey)
gnutls_datum_t tmp;
gnutls_x509_spki_st params;
+ memset(&params, 0, sizeof(params));
+
ret = _gnutls_x509_read_value(pkcs8_asn,
"privateKeyAlgorithm.parameters", &tmp);
if (ret < 0) {
+ if (ret == GNUTLS_E_ASN1_VALUE_NOT_FOUND || ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
+ goto skip_params;
+
gnutls_assert();
goto error;
}
@@ -973,6 +978,7 @@ _decode_pkcs8_rsa_pss_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey)
goto error;
}
+ skip_params:
ret = _decode_pkcs8_rsa_key(pkcs8_asn, pkey);
if (ret < 0) {
gnutls_assert();
diff --git a/lib/x509/sign.c b/lib/x509/sign.c
index 343b6eb969..c081a92c00 100644
--- a/lib/x509/sign.c
+++ b/lib/x509/sign.c
@@ -74,7 +74,7 @@ _gnutls_x509_crt_get_spki_params(gnutls_x509_crt_t crt,
gnutls_assert();
return GNUTLS_E_CERTIFICATE_ERROR;
}
- } else if (key_params->pk != GNUTLS_PK_RSA) {
+ } else if (key_params->pk != GNUTLS_PK_RSA && key_params->pk != GNUTLS_PK_UNKNOWN) {
gnutls_assert();
return GNUTLS_E_CERTIFICATE_ERROR;
}
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index 8e5a15c2c2..1da05109d8 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -1594,6 +1594,7 @@ gnutls_x509_crt_get_spki(gnutls_x509_crt_t cert, gnutls_x509_spki_t spki, unsign
return GNUTLS_E_INVALID_REQUEST;
}
+
spki->pk = gnutls_x509_crt_get_pk_algorithm(cert, NULL);
memset(&params, 0, sizeof(params));
@@ -1604,6 +1605,9 @@ gnutls_x509_crt_get_spki(gnutls_x509_crt_t cert, gnutls_x509_spki_t spki, unsign
return result;
}
+ if (params.pk == GNUTLS_PK_UNKNOWN)
+ return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+
spki->rsa_pss_dig = params.rsa_pss_dig;
spki->salt_size = params.salt_size;
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index c80a79fd11..6a7e5fcc96 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -256,8 +256,8 @@ _gnutls_x509_read_ecc_params(uint8_t * der, int dersize,
int _gnutls_asn1_encode_privkey(ASN1_TYPE * c2,
gnutls_pk_params_st * params, unsigned compat);
-int _gnutls_x509_privkey_get_spki_params(gnutls_x509_privkey_t key,
- gnutls_x509_spki_st * params);
+void _gnutls_x509_privkey_get_spki_params(gnutls_x509_privkey_t key,
+ gnutls_x509_spki_st * params);
int _gnutls_x509_read_rsa_pss_params(uint8_t * der, int dersize,
gnutls_x509_spki_st * params);
@@ -371,12 +371,13 @@ int _gnutls_x509_read_key_int(ASN1_TYPE node, const char *value,
int _gnutls_x509_write_key_int(ASN1_TYPE node, const char *value, bigint_t mpi,
int lz);
-int _gnutls_x509_read_sign_params(ASN1_TYPE src, const char *src_name,
- gnutls_x509_spki_st *params);
+int _gnutls_x509_read_pkalgo_params(ASN1_TYPE src, const char *src_name,
+ gnutls_x509_spki_st *params, unsigned is_sig);
int _gnutls_x509_write_sign_params(ASN1_TYPE dst, const char *dst_name,
const gnutls_sign_entry_st *se, gnutls_x509_spki_st *params);
-#define _gnutls_x509_read_spki_params _gnutls_x509_read_sign_params
+#define _gnutls_x509_read_sign_params(src,name,params) _gnutls_x509_read_pkalgo_params(src,name,params,1)
+#define _gnutls_x509_read_spki_params(src,name,params) _gnutls_x509_read_pkalgo_params(src,name,params,0)
int _gnutls_x509_write_spki_params(ASN1_TYPE dst, const char *dst_name,
gnutls_x509_spki_st *params);