From: Nikos Mavrogiannopoulos Date: Tue, 5 Aug 2014 09:02:30 +0000 (+0200) Subject: added new function to obtain information on a PKCS #12 encrypted bag X-Git-Tag: gnutls_3_4_0~1145 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2eba37d94a5931760e758eb4efe2b2d2fb42ea4e;p=thirdparty%2Fgnutls.git added new function to obtain information on a PKCS #12 encrypted bag New function: gnutls_pkcs12_bag_enc_info() --- diff --git a/lib/includes/gnutls/pkcs12.h b/lib/includes/gnutls/pkcs12.h index 8b024e502b..c348c20275 100644 --- a/lib/includes/gnutls/pkcs12.h +++ b/lib/includes/gnutls/pkcs12.h @@ -62,6 +62,10 @@ int gnutls_pkcs12_bag_decrypt(gnutls_pkcs12_bag_t bag, const char *pass); int gnutls_pkcs12_bag_encrypt(gnutls_pkcs12_bag_t bag, const char *pass, unsigned int flags); +int +gnutls_pkcs12_bag_enc_info(gnutls_pkcs12_bag_t bag, unsigned int *schema, unsigned int *cipher, + void *salt, unsigned int *salt_size, unsigned int *iter_count, char **oid); + #define GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED 1 int gnutls_pkcs12_simple_parse(gnutls_pkcs12_t p12, const char *password, diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 1c5944392c..bc5837d0ac 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1017,6 +1017,7 @@ GNUTLS_3_1_0 { gnutls_pkcs_schema_get_name; gnutls_pkcs_schema_get_oid; gnutls_pkcs8_info; + gnutls_pkcs12_bag_enc_info; } GNUTLS_3_0_0; GNUTLS_FIPS140 { diff --git a/lib/x509/pkcs12_bag.c b/lib/x509/pkcs12_bag.c index b77ea46cf4..6a0e27a0c8 100644 --- a/lib/x509/pkcs12_bag.c +++ b/lib/x509/pkcs12_bag.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2003-2012 Free Software Foundation, Inc. + * Copyright (C) 2003-2014 Free Software Foundation, Inc. + * Copyright (C) 2014 Red Hat * * Author: Nikos Mavrogiannopoulos * @@ -779,5 +780,77 @@ gnutls_pkcs12_bag_encrypt(gnutls_pkcs12_bag_t bag, const char *pass, bag->bag_elements = 1; + return 0; +} + +/** + * gnutls_pkcs12_bag_enc_info: + * @bag: The bag + * @schema: indicate the schema as one of %gnutls_pkcs_encrypt_flags_t + * @cipher: the cipher used as %gnutls_cipher_algorithm_t + * @salt: PBKDF2 salt (if non-NULL then @salt_size initially holds its size) + * @salt_size: PBKDF2 salt size + * @iter_count: PBKDF2 iteration count + * @oid: if non-NULL it will contain an allocated null-terminated variable with the OID + * + * This function will provide information on the encryption algorithms used + * in an encrypted bag. If the structure algorithms + * are unknown the code %GNUTLS_E_UNKNOWN_CIPHER_TYPE will be returned, + * and only @oid, will be set. That is, @oid will be set on encrypted bags + * whether supported or not. It must be deinitialized using gnutls_free(). + * The other variables are only set on supported structures. + * + * Returns: %GNUTLS_E_INVALID_REQUEST if the provided bag isn't encrypted, + * %GNUTLS_E_UNKNOWN_CIPHER_TYPE if the structure's encryption isn't supported, or + * another negative error code in case of a failure. Zero on success. + **/ +int +gnutls_pkcs12_bag_enc_info(gnutls_pkcs12_bag_t bag, unsigned int *schema, unsigned int *cipher, + void *salt, unsigned int *salt_size, unsigned int *iter_count, char **oid) +{ + int ret; + struct pbkdf2_params kdf; + const struct pbes2_schema_st *p; + + if (bag == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + if (bag->element[0].type != GNUTLS_BAG_ENCRYPTED) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + ret = + _gnutls_pkcs7_data_enc_info(&bag->element[0].data, &p, &kdf, oid); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + + if (schema) + *schema = p->flag; + + if (cipher) + *cipher = p->cipher; + + if (iter_count) + *iter_count = kdf.iter_count; + + if (salt) { + if (*salt_size >= (unsigned)kdf.salt_size) { + memcpy(salt, kdf.salt, kdf.salt_size); + } else { + *salt_size = kdf.salt_size; + return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); + } + } + + if (salt_size) + *salt_size = kdf.salt_size; + + return 0; } diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c index 7bb3a67511..c4abe60d4e 100644 --- a/lib/x509/privkey_pkcs8.c +++ b/lib/x509/privkey_pkcs8.c @@ -1,5 +1,7 @@ /* - * Copyright (C) 2003-2012 Free Software Foundation, Inc. + * Copyright (C) 2003-2014 Free Software Foundation, Inc. + * Copyright (C) 2014 Red Hat + * Copyright (C) 2014 Nikos Mavrogiannopoulos * * Author: Nikos Mavrogiannopoulos * @@ -640,12 +642,12 @@ gnutls_x509_privkey_export_pkcs8(gnutls_x509_privkey_t key, * * This function will provide information on the algorithms used * in a particular PKCS #8 structure. If the structure algorithms - * are unknown the return code will be %GNUTLS_E_UNKNOWN_CIPHER_TYPE, + * are unknown the code %GNUTLS_E_UNKNOWN_CIPHER_TYPE will be returned, * and only @oid, will be set. That is, @oid will be set on encrypted PKCS #8 - * structures whether supported or not. The other variables are only set - * on supported structures. + * structures whether supported or not. It must be deinitialized using gnutls_free(). + * The other variables are only set on supported structures. * - * Returns: %GNUTLS_E_DECRYPTION_FAILED if the provided structure isn't encrypted, + * Returns: %GNUTLS_E_INVALID_REQUEST if the provided structure isn't encrypted, * %GNUTLS_E_UNKNOWN_CIPHER_TYPE if the structure's encryption isn't supported, or * another negative error code in case of a failure. Zero on success. **/ @@ -692,6 +694,8 @@ gnutls_pkcs8_info(const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format, } ret = pkcs8_key_info(&_data, &p, &kdf, oid); + if (ret == GNUTLS_E_DECRYPTION_FAILED) + ret = GNUTLS_E_INVALID_REQUEST; if (ret < 0) { gnutls_assert(); goto cleanup; @@ -706,17 +710,21 @@ gnutls_pkcs8_info(const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format, if (cipher) *cipher = p->cipher; + if (iter_count) + *iter_count = kdf.iter_count; + if (salt) { if (*salt_size >= (unsigned)kdf.salt_size) { memcpy(salt, kdf.salt, kdf.salt_size); + } else { + *salt_size = kdf.salt_size; + return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); } } if (salt_size) *salt_size = kdf.salt_size; - if (iter_count) - *iter_count = kdf.iter_count; return 0; @@ -2433,7 +2441,7 @@ _gnutls_pkcs7_decrypt_data(const gnutls_datum_t * data, int _gnutls_pkcs7_data_enc_info(const gnutls_datum_t * data, const struct pbes2_schema_st **p, - struct pbkdf2_params *kdf_params) + struct pbkdf2_params *kdf_params, char **oid) { int result, len; char enc_oid[MAX_OID_SIZE]; @@ -2472,6 +2480,10 @@ _gnutls_pkcs7_data_enc_info(const gnutls_datum_t * data, const struct pbes2_sche goto error; } + if (oid) { + *oid = gnutls_strdup(enc_oid); + } + if ((result = check_pkcs12_schema(enc_oid)) < 0) { gnutls_assert(); goto error; diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h index 14277e7f66..69f1348e58 100644 --- a/lib/x509/x509_int.h +++ b/lib/x509/x509_int.h @@ -369,9 +369,10 @@ int _gnutls_pkcs_flags_to_schema(unsigned int flags); int _gnutls_pkcs7_encrypt_data(schema_id schema, const gnutls_datum_t * data, const char *password, gnutls_datum_t * enc); + int _gnutls_pkcs7_data_enc_info(const gnutls_datum_t * data, const struct pbes2_schema_st **p, - struct pbkdf2_params *kdf_params); + struct pbkdf2_params *kdf_params, char **oid); int _pkcs12_decode_safe_contents(const gnutls_datum_t * content, gnutls_pkcs12_bag_t bag);