Improve & test legacy mbedtls_pkcs12_pbe
* Prevent pkcs12_pbe encryption when PKCS7 padding has been
disabled since this not part of the specs.
* Allow decryption when PKCS7 padding is disabled for legacy
reasons, However, invalid padding is not checked.
* Document new behaviour, known limitations and possible
security concerns.
* Add tests to check these scenarios. Test data has been
generated by the below code using OpenSSL as a reference:
int main()
{
char pass[] = "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB";
unsigned char salt[] = "\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC";
unsigned char plaintext[] = "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA";
unsigned char *ciphertext = NULL;
int iter = 10;
X509_ALGOR *alg = X509_ALGOR_new();
int ciphertext_len = 0;
int alg_nid = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
alg->parameter = ASN1_TYPE_new();
struct asn1_object_st * aobj;
PKCS5_pbe_set0_algor(alg, alg_nid, iter,
salt, sizeof(salt)-1);
aobj = alg->algorithm;
printf("\"30%.2X", 2 + aobj->length + alg->parameter->value.asn1_string->length);
printf("06%.2X", aobj->length);
for (int i = 0; i < aobj->length; i++) {
printf("%.2X", aobj->data[i]);
}
for (int i = 0; i < alg->parameter->value.asn1_string->length; i++) {
printf("%.2X", alg->parameter->value.asn1_string->data[i]);
}
printf("\":\"");
for (int i = 0; i < sizeof(pass)-1; i++) {
printf("%.2X", pass[i] & 0xFF);
}
printf("\":\"");
for (int i = 0; i < sizeof(plaintext)-1; i++) {
printf("%.2X", plaintext[i]);
}
printf("\":");
printf("0");
printf(":\"");
unsigned char * res = PKCS12_pbe_crypt(alg, pass, sizeof(pass)-1, plaintext, sizeof(plaintext)-1, &ciphertext, &ciphertext_len, 1);
if (res == NULL)
printf("Encryption failed!\n");
for (int i = 0; i < ciphertext_len; i++) {
printf("%.2X", res[i]);
}
printf("\"\n");
return 0;
}
Signed-off-by: Waleed Elmelegy <waleed.elmelegy@arm.com>
diff --git a/tests/suites/test_suite_pkcs12.function b/tests/suites/test_suite_pkcs12.function
index 17d2ed7..5f758df 100644
--- a/tests/suites/test_suite_pkcs12.function
+++ b/tests/suites/test_suite_pkcs12.function
@@ -1,6 +1,8 @@
/* BEGIN_HEADER */
#include "mbedtls/pkcs12.h"
#include "mbedtls/error.h"
+#include "mbedtls/oid.h"
+#include "common.h"
typedef enum {
USE_NULL_INPUT = 0,
@@ -14,7 +16,7 @@
* END_DEPENDENCIES
*/
-/* BEGIN_CASE */
+/* BEGIN_CASE MBEDTLS_ASN1_PARSE_C*/
void pkcs12_derive_key(int md_type, int key_size_arg,
data_t *password_arg, int password_usage,
data_t *salt_arg, int salt_usage,
@@ -66,3 +68,79 @@
}
/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ASN1_PARSE_C */
+void pkcs12_pbe_encrypt(data_t *params_hex, data_t *pw,
+ data_t *data, int ref_ret, data_t *ref_out)
+{
+ int my_ret;
+ mbedtls_asn1_buf pbe_alg_oid, pbe_params;
+ unsigned char *my_out = NULL;
+ unsigned char *p, *end;
+ mbedtls_cipher_type_t cipher_alg;
+ mbedtls_md_type_t md_alg;
+
+ p = params_hex->x;
+ end = p + params_hex->len;
+
+ my_ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params);
+ if (my_ret) {
+ TEST_HELPER_ASSERT(0);
+ }
+ my_ret = mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg);
+ if (my_ret) {
+ TEST_HELPER_ASSERT(0);
+ }
+
+ ASSERT_ALLOC(my_out, ref_out->len);
+
+ my_ret = mbedtls_pkcs12_pbe(&pbe_params, MBEDTLS_PKCS12_PBE_ENCRYPT, cipher_alg,
+ md_alg, pw->x, pw->len, data->x, data->len, my_out);
+ TEST_EQUAL(my_ret, ref_ret);
+ if (ref_ret == 0) {
+ ASSERT_COMPARE(my_out, ref_out->len,
+ ref_out->x, ref_out->len);
+ }
+
+exit:
+ mbedtls_free(my_out);
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ASN1_PARSE_C */
+void pkcs12_pbe_decrypt(data_t *params_hex, data_t *pw,
+ data_t *data, int ref_ret, data_t *ref_out)
+{
+ int my_ret;
+ mbedtls_asn1_buf pbe_alg_oid, pbe_params;
+ unsigned char *my_out = NULL;
+ unsigned char *p, *end;
+ mbedtls_cipher_type_t cipher_alg;
+ mbedtls_md_type_t md_alg;
+
+ p = params_hex->x;
+ end = p + params_hex->len;
+
+ my_ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params);
+ if (my_ret) {
+ TEST_HELPER_ASSERT(0);
+ }
+ my_ret = mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg);
+ if (my_ret) {
+ TEST_HELPER_ASSERT(0);
+ }
+
+ ASSERT_ALLOC(my_out, ref_out->len);
+
+ my_ret = mbedtls_pkcs12_pbe(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, cipher_alg,
+ md_alg, pw->x, pw->len, data->x, data->len, my_out);
+ TEST_EQUAL(my_ret, ref_ret);
+ if (ref_ret == 0) {
+ ASSERT_COMPARE(my_out, ref_out->len,
+ ref_out->x, ref_out->len);
+ }
+
+exit:
+ mbedtls_free(my_out);
+}
+/* END_CASE */