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 */