/* "Short Description", Error code define, critical (0,1) -- 1 in most cases */
ERROR_ENTRY("Success.", GNUTLS_E_SUCCESS, 0 ),
ERROR_ENTRY("Could not negotiate a supported cipher suite.", GNUTLS_E_UNKNOWN_CIPHER_SUITE, 1 ),
+ ERROR_ENTRY("The cipher type is unknown.", GNUTLS_E_UNKNOWN_CIPHER_TYPE, 1 ),
ERROR_ENTRY("The certificate and the given key do not match.", GNUTLS_E_CERTIFICATE_KEY_MISMATCH, 1 ),
ERROR_ENTRY("Could not negotiate a supported compression method.", GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM, 1 ),
ERROR_ENTRY("An unknown public key algorithm was encountered.", GNUTLS_E_UNKNOWN_PK_ALGORITHM, 1 ),
int _gnutls_x509_read_value( ASN1_TYPE c, const char* root, gnutls_datum *ret, int str);
-int _gnutls_x509_decrypt_pkcs7_encrypted_data( const gnutls_datum* data,
- const char* password, gnutls_datum* dec);
output_data, output_data_size);
}
-#define BAG_PKCS8_KEY "1.2.840.113549.1.12.10.1.1"
-#define BAG_PKCS8_ENCRYPTED_KEY "1.2.840.113549.1.12.10.1.2"
-#define BAG_CERTIFICATE "1.2.840.113549.1.12.10.1.3"
-#define BAG_CRL "1.2.840.113549.1.12.10.1.4"
-
static int _oid2bag( const char* oid)
{
if (strcmp(oid, BAG_PKCS8_KEY)==0)
}
-
-static
-int _parse_safe_contents( ASN1_TYPE sc, const char* sc_name, gnutls_pkcs12_bag bag)
+/* Decodes the SafeContents, and puts the output in
+ * the given bag.
+ */
+int
+_pkcs12_decode_safe_contents( const gnutls_datum* content, gnutls_pkcs12_bag bag)
{
char oid[128];
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
-gnutls_datum content = { NULL, 0 };
int len, result;
int bag_type;
- /* Step 1. Extract the content.
- */
-
- result = _gnutls_x509_read_value(sc, sc_name, &content, 1);
- if (result < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- /* Step 2. Extract the SEQUENCE.
+ /* Step 1. Extract the SEQUENCE.
*/
if ((result=asn1_create_element
goto cleanup;
}
- result = asn1_der_decoding(&c2, content.data, content.size, NULL);
+ result = asn1_der_decoding(&c2, content->data, content->size, NULL);
if (result != ASN1_SUCCESS) {
gnutls_assert();
result = _gnutls_asn2err(result);
goto cleanup;
}
- _gnutls_free_datum(&content);
len = sizeof(oid);
result = asn1_read_value(c2, "?1.bagId", oid, &len);
/* Read the Bag Value
*/
-
result = _gnutls_x509_read_value( c2, "?1.bagValue", &bag->data, 0);
if (result < 0) {
gnutls_assert();
cleanup:
if (c2) asn1_delete_structure(&c2);
+ return result;
+
+}
+
+
+static
+int _parse_safe_contents( ASN1_TYPE sc, const char* sc_name, gnutls_pkcs12_bag bag)
+{
+gnutls_datum content = { NULL, 0 };
+int result;
+
+ /* Step 1. Extract the content.
+ */
+
+ result = _gnutls_x509_read_value(sc, sc_name, &content, 1);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _pkcs12_decode_safe_contents( &content, bag);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ _gnutls_free_datum( &content);
+
+ return 0;
+
+ cleanup:
_gnutls_free_datum( &content);
return result;
}
gnutls_pkcs12_bag_type type;
} gnutls_pkcs12_bag_int;
+#define BAG_PKCS8_KEY "1.2.840.113549.1.12.10.1.1"
+#define BAG_PKCS8_ENCRYPTED_KEY "1.2.840.113549.1.12.10.1.2"
+#define BAG_CERTIFICATE "1.2.840.113549.1.12.10.1.3"
+#define BAG_CRL "1.2.840.113549.1.12.10.1.4"
+
typedef struct gnutls_pkcs12_int *gnutls_pkcs12;
typedef struct gnutls_pkcs12_bag_int *gnutls_pkcs12_bag;
int
_pkcs12_string_to_key (int id, const char *salt, int salt_size, int iter, const char *pw,
int req_keylen, unsigned char *keybuf);
+
+int _gnutls_x509_decrypt_pkcs7_encrypted_data( const gnutls_datum* data,
+ const char* password, gnutls_datum* dec);
+int _pkcs12_decode_safe_contents( const gnutls_datum* content, gnutls_pkcs12_bag bag);
{
int ret;
gnutls_datum dec;
+ASN1_TYPE sc = ASN1_TYPE_EMPTY;
ret = _gnutls_x509_decrypt_pkcs7_encrypted_data(
&bag->data, pass, &dec);
if (ret < 0) {
- gnutls_assert();
+ gnutls_assert();
return ret;
}
-
- /* decryption succeeded */
-
+
+ /* decryption succeeded. Now decode the SafeContents
+ * stuff, and parse it.
+ */
+
_gnutls_free_datum( &bag->data);
-
- bag->data = dec;
+
+ ret = _pkcs12_decode_safe_contents( &dec, bag);
+
+ _gnutls_free_datum( &dec);
+
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
return 0;
}
typedef enum schema_id {
PBES2, /* the stuff in PKCS #5 */
- PKCS12_3DES_SHA1 /* the fucking stuff in PKCS #12 */
+ PKCS12_3DES_SHA1, /* the fucking stuff in PKCS #12 */
+ PKCS12_ARCFOUR_SHA1
} schema_id;
#define PBES2_OID "1.2.840.113549.1.5.13"
#define DES_EDE3_CBC_OID "1.2.840.113549.3.7"
/* oid_pbeWithSHAAnd3_KeyTripleDES_CBC */
-#define PBE_3DES_SHA1_OID "1.2.840.113549.1.12.1.3"
+#define PKCS12_PBE_3DES_SHA1_OID "1.2.840.113549.1.12.1.3"
+#define PKCS12_PBE_ARCFOUR_SHA1_OID "1.2.840.113549.1.12.1.1"
struct pbkdf2_params {
opaque salt[32];
if (strcmp(oid, PBES2_OID) == 0)
return PBES2;
- if (strcmp(oid, PBE_3DES_SHA1_OID) == 0)
+ if (strcmp(oid, PKCS12_PBE_3DES_SHA1_OID) == 0)
return PKCS12_3DES_SHA1;
+ if (strcmp(oid, PKCS12_PBE_ARCFOUR_SHA1_OID) == 0)
+ return PKCS12_ARCFOUR_SHA1;
+
_gnutls_x509_log("PKCS encryption schema OID '%s' is unsupported.\n", oid);
return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
break;
case PKCS12_3DES_SHA1:
+ case PKCS12_ARCFOUR_SHA1:
+
+ if ((schema) == PKCS12_3DES_SHA1) {
+ enc_params->cipher = GNUTLS_CIPHER_3DES_CBC;
+ enc_params->iv_size = 8;
+ } else {
+ enc_params->cipher = GNUTLS_CIPHER_ARCFOUR_128;
+ enc_params->iv_size = 0;
+ }
+
if ((result =
asn1_create_element(_gnutls_get_pkix(),
"PKIX1.pkcs-12-PbeParams",
goto error;
}
- enc_params->cipher = GNUTLS_CIPHER_3DES_CBC;
- enc_params->iv_size = 8;
- _pkcs12_string_to_key( 2/*IV*/, kdf_params->salt, kdf_params->salt_size,
- kdf_params->iter_count, password, 8, enc_params->iv);
+ if (enc_params->iv_size)
+ _pkcs12_string_to_key( 2/*IV*/, kdf_params->salt, kdf_params->salt_size,
+ kdf_params->iter_count, password, enc_params->iv_size, enc_params->iv);
asn1_delete_structure(&pbes2_asn);
goto error;
}
- /* we only support PBES2
- */
if ((result = check_schema(enc_oid)) < 0) {
gnutls_assert();
goto error;