diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2009-10-24 17:38:25 +0300 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2009-10-24 17:46:12 +0300 |
commit | 68996b00292596980d5ca440a434ebc32cf4c7c1 (patch) | |
tree | e54a55262bfee0c52fa62daa93757672c6c82463 | |
parent | 0cb109c4bf24899adc9103a832169f7881d59218 (diff) | |
download | gnutls-68996b00292596980d5ca440a434ebc32cf4c7c1.tar.gz |
Added support for the AES family of ciphers in the PKCS8 and 12 encryption options.
-rw-r--r-- | doc/manpages/certtool.1 | 3 | ||||
-rw-r--r-- | lib/cipher-libgcrypt.c | 6 | ||||
-rw-r--r-- | lib/gnutls_algorithms.c | 1 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 1 | ||||
-rw-r--r-- | lib/includes/gnutls/x509.h | 5 | ||||
-rw-r--r-- | lib/pkix.asn | 3 | ||||
-rw-r--r-- | lib/pkix_asn1_tab.c | 6 | ||||
-rw-r--r-- | lib/x509/pkcs12_bag.c | 9 | ||||
-rw-r--r-- | lib/x509/privkey_pkcs8.c | 465 | ||||
-rw-r--r-- | lib/x509/x509_int.h | 7 | ||||
-rw-r--r-- | src/certtool-gaa.c | 189 | ||||
-rw-r--r-- | src/certtool-gaa.h | 4 | ||||
-rw-r--r-- | src/certtool.c | 28 | ||||
-rw-r--r-- | src/certtool.gaa | 5 |
14 files changed, 483 insertions, 249 deletions
diff --git a/doc/manpages/certtool.1 b/doc/manpages/certtool.1 index f581a274ee..53df4baa6c 100644 --- a/doc/manpages/certtool.1 +++ b/doc/manpages/certtool.1 @@ -61,6 +61,9 @@ Update a signed certificate. .SS Controlling output .IP "\-8, \-\-pkcs8" Use PKCS #8 format for private keys. +.IP "\-\-pkcs-cipher" +The cipher to use when doing pkcs encryption. Valid options are +3des,aes-128,aes-192,aes-256,rc2-40 .IP "\-\-dsa" Generate a DSA key. .IP "\-\-bits BITS" diff --git a/lib/cipher-libgcrypt.c b/lib/cipher-libgcrypt.c index 46b3ff7618..16aba8dc8d 100644 --- a/lib/cipher-libgcrypt.c +++ b/lib/cipher-libgcrypt.c @@ -47,6 +47,12 @@ wrap_gcry_cipher_init (gnutls_cipher_algorithm_t algo, void **ctx) GCRY_CIPHER_MODE_CBC, 0); break; + case GNUTLS_CIPHER_AES_192_CBC: + err = + gcry_cipher_open ((gcry_cipher_hd_t *) ctx, GCRY_CIPHER_AES192, + GCRY_CIPHER_MODE_CBC, 0); + break; + case GNUTLS_CIPHER_AES_256_CBC: err = gcry_cipher_open ((gcry_cipher_hd_t *) ctx, GCRY_CIPHER_AES256, diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c index bfd854574c..8f1eb9fc05 100644 --- a/lib/gnutls_algorithms.c +++ b/lib/gnutls_algorithms.c @@ -158,6 +158,7 @@ typedef struct gnutls_cipher_entry gnutls_cipher_entry; */ static const gnutls_cipher_entry algorithms[] = { {"AES-256-CBC", GNUTLS_CIPHER_AES_256_CBC, 16, 32, CIPHER_BLOCK, 16, 0}, + {"AES-192-CBC", GNUTLS_CIPHER_AES_192_CBC, 16, 24, CIPHER_BLOCK, 16, 0}, {"AES-128-CBC", GNUTLS_CIPHER_AES_128_CBC, 16, 16, CIPHER_BLOCK, 16, 0}, {"3DES-CBC", GNUTLS_CIPHER_3DES_CBC, 8, 24, CIPHER_BLOCK, 8, 0}, {"DES-CBC", GNUTLS_CIPHER_DES_CBC, 8, 8, CIPHER_BLOCK, 8, 0}, diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 7463fcb0e6..a4fe3fc67f 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -77,6 +77,7 @@ extern "C" { GNUTLS_CIPHER_CAMELLIA_256_CBC, GNUTLS_CIPHER_RC2_40_CBC = 90, GNUTLS_CIPHER_DES_CBC, + GNUTLS_CIPHER_AES_192_CBC, /* used only for PGP internals. Ignored in TLS/SSL */ diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h index e61ef25684..81ae14ddb9 100644 --- a/lib/includes/gnutls/x509.h +++ b/lib/includes/gnutls/x509.h @@ -578,7 +578,10 @@ extern "C" GNUTLS_PKCS_USE_PKCS12_3DES = 2, GNUTLS_PKCS_USE_PKCS12_ARCFOUR = 4, GNUTLS_PKCS_USE_PKCS12_RC2_40 = 8, - GNUTLS_PKCS_USE_PBES2_3DES = 16 + GNUTLS_PKCS_USE_PBES2_3DES = 16, + GNUTLS_PKCS_USE_PBES2_AES_128 = 32, + GNUTLS_PKCS_USE_PBES2_AES_192 = 64, + GNUTLS_PKCS_USE_PBES2_AES_256 = 128, } gnutls_pkcs_encrypt_flags_t; #define GNUTLS_PKCS8_PLAIN GNUTLS_PKCS_PLAIN diff --git a/lib/pkix.asn b/lib/pkix.asn index 7c85ff422c..51cd729951 100644 --- a/lib/pkix.asn +++ b/lib/pkix.asn @@ -511,6 +511,9 @@ pkcs-8-EncryptedData ::= OCTET STRING -- PKCS #5 stuff pkcs-5-des-EDE3-CBC-params ::= OCTET STRING (SIZE(8)) +pkcs-5-aes128-CBC-params ::= OCTET STRING (SIZE(16)) +pkcs-5-aes192-CBC-params ::= OCTET STRING (SIZE(16)) +pkcs-5-aes256-CBC-params ::= OCTET STRING (SIZE(16)) pkcs-5-PBES2-params ::= SEQUENCE { keyDerivationFunc AlgorithmIdentifier, diff --git a/lib/pkix_asn1_tab.c b/lib/pkix_asn1_tab.c index 1d8a37d1f9..1139a5f93f 100644 --- a/lib/pkix_asn1_tab.c +++ b/lib/pkix_asn1_tab.c @@ -424,6 +424,12 @@ const ASN1_ARRAY_TYPE pkix_asn1_tab[] = { { "pkcs-8-EncryptedData", 1073741831, NULL }, { "pkcs-5-des-EDE3-CBC-params", 1612709895, NULL }, { NULL, 1048586, "8"}, + { "pkcs-5-aes128-CBC-params", 1612709895, NULL }, + { NULL, 1048586, "16"}, + { "pkcs-5-aes192-CBC-params", 1612709895, NULL }, + { NULL, 1048586, "16"}, + { "pkcs-5-aes256-CBC-params", 1612709895, NULL }, + { NULL, 1048586, "16"}, { "pkcs-5-PBES2-params", 1610612741, NULL }, { "keyDerivationFunc", 1073741826, "AlgorithmIdentifier"}, { "encryptionScheme", 2, "AlgorithmIdentifier"}, diff --git a/lib/x509/pkcs12_bag.c b/lib/x509/pkcs12_bag.c index d38f38b984..4e28348968 100644 --- a/lib/x509/pkcs12_bag.c +++ b/lib/x509/pkcs12_bag.c @@ -740,14 +740,7 @@ gnutls_pkcs12_bag_encrypt (gnutls_pkcs12_bag_t bag, const char *pass, return GNUTLS_E_INVALID_REQUEST; } - if (flags & GNUTLS_PKCS_USE_PKCS12_ARCFOUR) - id = PKCS12_ARCFOUR_SHA1; - else if (flags & GNUTLS_PKCS_USE_PKCS12_RC2_40) - id = PKCS12_RC2_40_SHA1; - else if (flags & GNUTLS_PKCS_USE_PBES2_3DES) - id = PBES2; - else - id = PKCS12_3DES_SHA1; + id = _gnutls_pkcs_flags_to_schema(flags); /* Now encrypt them. */ diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c index faeb298db6..5bff37daf9 100644 --- a/lib/x509/privkey_pkcs8.c +++ b/lib/x509/privkey_pkcs8.c @@ -42,6 +42,9 @@ #define PBES2_OID "1.2.840.113549.1.5.13" #define PBKDF2_OID "1.2.840.113549.1.5.12" #define DES_EDE3_CBC_OID "1.2.840.113549.3.7" +#define AES_128_CBC_OID "2.16.840.1.101.3.4.1.2" +#define AES_192_CBC_OID "2.16.840.1.101.3.4.1.22" +#define AES_256_CBC_OID "2.16.840.1.101.3.4.1.42" #define DES_CBC_OID "1.3.14.3.2.7" /* oid_pbeWithSHAAnd3_KeyTripleDES_CBC */ @@ -60,7 +63,7 @@ struct pbkdf2_params struct pbe_enc_params { gnutls_cipher_algorithm_t cipher; - opaque iv[8]; + opaque iv[MAX_CIPHER_BLOCK_SIZE]; int iv_size; }; @@ -105,7 +108,7 @@ check_schema (const char *oid) { if (strcmp (oid, PBES2_OID) == 0) - return PBES2; + return PBES2_GENERIC; /* ok */ if (strcmp (oid, PKCS12_PBE_3DES_SHA1_OID) == 0) return PKCS12_3DES_SHA1; @@ -388,7 +391,10 @@ encode_to_pkcs8_key (schema_id schema, const gnutls_datum_t * der_key, */ switch (schema) { - case PBES2: + case PBES2_3DES: + case PBES2_AES_128: + case PBES2_AES_192: + case PBES2_AES_256: result = asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm", PBES2_OID, 1); @@ -472,6 +478,31 @@ error: return result; } +int _gnutls_pkcs_flags_to_schema(unsigned int flags) +{ +int schema; + + if (flags & GNUTLS_PKCS_USE_PKCS12_ARCFOUR) + schema = PKCS12_ARCFOUR_SHA1; + else if (flags & GNUTLS_PKCS_USE_PKCS12_RC2_40) + schema = PKCS12_RC2_40_SHA1; + else if (flags & GNUTLS_PKCS_USE_PBES2_3DES) + schema = PBES2_3DES; + else if (flags & GNUTLS_PKCS_USE_PBES2_AES_128) + schema = PBES2_AES_128; + else if (flags & GNUTLS_PKCS_USE_PBES2_AES_192) + schema = PBES2_AES_192; + else if (flags & GNUTLS_PKCS_USE_PBES2_AES_256) + schema = PBES2_AES_256; + else { + gnutls_assert(); + _gnutls_x509_log + ("Selecting default encryption PKCS12_3DES_SHA1 (flags: %u).\n", flags); + schema = PKCS12_3DES_SHA1; + } + + return schema; +} /** * gnutls_x509_privkey_export_pkcs8 - This function will export the private key to PKCS8 format @@ -532,15 +563,7 @@ gnutls_x509_privkey_export_pkcs8 (gnutls_x509_privkey_t key, return ret; } - if (flags & GNUTLS_PKCS_USE_PKCS12_3DES) - schema = PKCS12_3DES_SHA1; - else if (flags & GNUTLS_PKCS_USE_PKCS12_ARCFOUR) - schema = PKCS12_ARCFOUR_SHA1; - else if (flags & GNUTLS_PKCS_USE_PKCS12_RC2_40) - schema = PKCS12_RC2_40_SHA1; - else - schema = PBES2; - + schema = _gnutls_pkcs_flags_to_schema(flags); if ((flags & GNUTLS_PKCS_PLAIN) || password == NULL) { @@ -576,12 +599,34 @@ gnutls_x509_privkey_export_pkcs8 (gnutls_x509_privkey_t key, return ret; } +static int cipher_to_schema(int cipher) +{ + switch(cipher) + { + case GNUTLS_CIPHER_AES_128_CBC: + return PBES2_AES_128; + break; + case GNUTLS_CIPHER_AES_192_CBC: + return PBES2_AES_192; + break; + case GNUTLS_CIPHER_AES_256_CBC: + return PBES2_AES_256; + break; + case GNUTLS_CIPHER_3DES_CBC: + return PBES2_3DES; + break; + default: + return GNUTLS_E_UNKNOWN_CIPHER_TYPE; + break; + } +} + /* Read the parameters cipher, IV, salt etc using the given * schema ID. */ static int -read_pkcs_schema_params (schema_id schema, const char *password, +read_pkcs_schema_params (schema_id *schema, const char *password, const opaque * data, int data_size, struct pbkdf2_params *kdf_params, struct pbe_enc_params *enc_params) @@ -590,10 +635,10 @@ read_pkcs_schema_params (schema_id schema, const char *password, int result; gnutls_datum_t tmp; - switch (schema) + switch (*schema) { - case PBES2: + case PBES2_GENERIC: /* Now check the key derivation and the encryption * functions. @@ -638,24 +683,32 @@ read_pkcs_schema_params (schema_id schema, const char *password, } asn1_delete_structure (&pbes2_asn); + + result = cipher_to_schema(enc_params->cipher); + if (result < 0) + { + gnutls_assert(); + goto error; + } + + *schema = result; return 0; - break; case PKCS12_3DES_SHA1: case PKCS12_ARCFOUR_SHA1: case PKCS12_RC2_40_SHA1: - if ((schema) == PKCS12_3DES_SHA1) + if ((*schema) == PKCS12_3DES_SHA1) { enc_params->cipher = GNUTLS_CIPHER_3DES_CBC; enc_params->iv_size = 8; } - else if ((schema) == PKCS12_ARCFOUR_SHA1) + else if ((*schema) == PKCS12_ARCFOUR_SHA1) { enc_params->cipher = GNUTLS_CIPHER_ARCFOUR_128; enc_params->iv_size = 0; } - else if ((schema) == PKCS12_RC2_40_SHA1) + else if ((*schema) == PKCS12_RC2_40_SHA1) { enc_params->cipher = GNUTLS_CIPHER_RC2_40_CBC; enc_params->iv_size = 8; @@ -707,8 +760,9 @@ read_pkcs_schema_params (schema_id schema, const char *password, asn1_delete_structure (&pbes2_asn); return 0; - break; - + + default: + gnutls_assert(); } /* switch */ return GNUTLS_E_UNKNOWN_CIPHER_TYPE; @@ -790,7 +844,7 @@ decode_pkcs8_key (const gnutls_datum_t * raw_key, params_len = params_end - params_start + 1; result = - read_pkcs_schema_params (schema, password, + read_pkcs_schema_params (&schema, password, &raw_key->data[params_start], params_len, &kdf_params, &enc_params); @@ -1346,17 +1400,62 @@ oid2cipher (const char *oid, gnutls_cipher_algorithm_t * algo) *algo = GNUTLS_CIPHER_3DES_CBC; return 0; } - + else if (strcmp (oid, DES_CBC_OID) == 0) { *algo = GNUTLS_CIPHER_DES_CBC; return 0; } + else + if (strcmp (oid, AES_128_CBC_OID) == 0) + { + *algo = GNUTLS_CIPHER_AES_128_CBC; + return 0; + } + else + if (strcmp (oid, AES_192_CBC_OID) == 0) + { + *algo = GNUTLS_CIPHER_AES_192_CBC; + return 0; + } + else + if (strcmp (oid, AES_256_CBC_OID) == 0) + { + *algo = GNUTLS_CIPHER_AES_256_CBC; + return 0; + } _gnutls_x509_log ("PKCS #8 encryption OID '%s' is unsupported.\n", oid); return GNUTLS_E_UNKNOWN_CIPHER_TYPE; } +static const char* cipher_to_pkcs_params(int cipher, const char** oid) +{ + switch(cipher) + { + case GNUTLS_CIPHER_AES_128_CBC: + if (oid) *oid = AES_128_CBC_OID; + return "PKIX1.pkcs-5-aes128-CBC-params"; + break; + case GNUTLS_CIPHER_AES_192_CBC: + if (oid) *oid = AES_192_CBC_OID; + return "PKIX1.pkcs-5-aes192-CBC-params"; + break; + case GNUTLS_CIPHER_AES_256_CBC: + if (oid) *oid = AES_256_CBC_OID; + return "PKIX1.pkcs-5-aes256-CBC-params"; + break; + case GNUTLS_CIPHER_3DES_CBC: + if (oid) *oid = DES_EDE3_CBC_OID; + return "PKIX1.pkcs-5-des-EDE3-CBC-params"; + break; + default: + return NULL; + break; + } +} + + static int read_pbe_enc_params (ASN1_TYPE pbes2_asn, @@ -1367,6 +1466,7 @@ read_pbe_enc_params (ASN1_TYPE pbes2_asn, int params_len, len, result; ASN1_TYPE pbe_asn = ASN1_TYPE_EMPTY; char oid[64]; + const char* eparams; memset (params, 0, sizeof (params)); @@ -1401,9 +1501,16 @@ read_pbe_enc_params (ASN1_TYPE pbes2_asn, /* Now check the encryption parameters. */ + eparams = cipher_to_pkcs_params( params->cipher, NULL); + if (eparams == NULL) + { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + if ((result = asn1_create_element (_gnutls_get_pkix (), - "PKIX1.pkcs-5-des-EDE3-CBC-params", + eparams, &pbe_asn)) != ASN1_SUCCESS) { gnutls_assert (); @@ -1493,31 +1600,35 @@ decrypt_data (schema_id schema, ASN1_TYPE pkcs8_asn, /* generate the key */ - if (schema == PBES2) + switch(schema) { - result = _gnutls_pbkdf2_sha1 (password, strlen (password), + case PBES2_3DES: + case PBES2_AES_128: + case PBES2_AES_192: + case PBES2_AES_256: + + result = _gnutls_pbkdf2_sha1 (password, strlen (password), kdf_params->salt, kdf_params->salt_size, kdf_params->iter_count, key, key_size); - if (result < 0) - { - gnutls_assert (); - goto error; - } - } - else - { - result = - _gnutls_pkcs12_string_to_key (1 /*KEY*/, kdf_params->salt, - kdf_params->salt_size, + if (result < 0) + { + gnutls_assert (); + goto error; + } + break; + default: + result = + _gnutls_pkcs12_string_to_key (1 /*KEY*/, kdf_params->salt, + kdf_params->salt_size, kdf_params->iter_count, password, key_size, key); - if (result < 0) - { - gnutls_assert (); - goto error; - } + if (result < 0) + { + gnutls_assert (); + goto error; + } } /* do the decryption. @@ -1675,30 +1786,39 @@ error: } + static int write_pbe_enc_params (ASN1_TYPE pbes2_asn, const struct pbe_enc_params *params) { int result; ASN1_TYPE pbe_asn = ASN1_TYPE_EMPTY; + const char* oid, *eparams; /* Write the encryption algorithm */ + eparams = cipher_to_pkcs_params(params->cipher, &oid); + if (eparams == NULL) + { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + result = asn1_write_value (pbes2_asn, "encryptionScheme.algorithm", - DES_EDE3_CBC_OID, 1); + oid, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); goto error; } - _gnutls_hard_log ("encryptionScheme.algorithm: %s\n", DES_EDE3_CBC_OID); + _gnutls_hard_log ("encryptionScheme.algorithm: %s\n", oid); /* Now check the encryption parameters. */ if ((result = asn1_create_element (_gnutls_get_pkix (), - "PKIX1.pkcs-5-des-EDE3-CBC-params", + eparams, &pbe_asn)) != ASN1_SUCCESS) { gnutls_assert (); @@ -1747,17 +1867,6 @@ generate_key (schema_id schema, opaque rnd[2]; int ret; - /* We should use the flags here to use different - * encryption algorithms etc. - */ - - if (schema == PKCS12_ARCFOUR_SHA1) - enc_params->cipher = GNUTLS_CIPHER_ARCFOUR_128; - else if (schema == PKCS12_3DES_SHA1) - enc_params->cipher = GNUTLS_CIPHER_3DES_CBC; - else if (schema == PKCS12_RC2_40_SHA1) - enc_params->cipher = GNUTLS_CIPHER_RC2_40_CBC; - ret = _gnutls_rnd (GNUTLS_RND_RANDOM, rnd, 2); if (ret < 0) { @@ -1766,12 +1875,40 @@ generate_key (schema_id schema, } /* generate salt */ - - if (schema == PBES2) - kdf_params->salt_size = - MIN (sizeof (kdf_params->salt), (unsigned) (10 + (rnd[1] % 10))); - else - kdf_params->salt_size = 8; + kdf_params->salt_size = + MIN (sizeof (kdf_params->salt), (unsigned) (10 + (rnd[1] % 10))); + + switch(schema) + { + case PBES2_3DES: + enc_params->cipher = GNUTLS_CIPHER_3DES_CBC; + break; + case PBES2_AES_128: + enc_params->cipher = GNUTLS_CIPHER_AES_128_CBC; + break; + case PBES2_AES_192: + enc_params->cipher = GNUTLS_CIPHER_AES_192_CBC; + break; + case PBES2_AES_256: + enc_params->cipher = GNUTLS_CIPHER_AES_256_CBC; + break; + /* non PBES2 algorithms */ + case PKCS12_ARCFOUR_SHA1: + enc_params->cipher = GNUTLS_CIPHER_ARCFOUR_128; + kdf_params->salt_size = 8; + break; + case PKCS12_3DES_SHA1: + enc_params->cipher = GNUTLS_CIPHER_3DES_CBC; + kdf_params->salt_size = 8; + break; + case PKCS12_RC2_40_SHA1: + enc_params->cipher = GNUTLS_CIPHER_RC2_40_CBC; + kdf_params->salt_size = 8; + break; + default: + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } ret = _gnutls_rnd (GNUTLS_RND_RANDOM, kdf_params->salt, kdf_params->salt_size); @@ -1786,7 +1923,6 @@ generate_key (schema_id schema, gnutls_cipher_get_key_size (enc_params->cipher); enc_params->iv_size = _gnutls_cipher_get_iv_size (enc_params->cipher); - key->data = gnutls_secure_malloc (key->size); if (key->data == NULL) { @@ -1797,59 +1933,63 @@ generate_key (schema_id schema, /* now generate the key. */ - if (schema == PBES2) + switch(schema) { + case PBES2_3DES: + case PBES2_AES_128: + case PBES2_AES_192: + case PBES2_AES_256: - ret = _gnutls_pbkdf2_sha1 (password, strlen (password), + ret = _gnutls_pbkdf2_sha1 (password, strlen (password), kdf_params->salt, kdf_params->salt_size, kdf_params->iter_count, key->data, kdf_params->key_size); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - if (enc_params->iv_size) - { - ret = _gnutls_rnd (GNUTLS_RND_NONCE, + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + if (enc_params->iv_size) + { + ret = _gnutls_rnd (GNUTLS_RND_NONCE, enc_params->iv, enc_params->iv_size); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - } - } - else - { /* PKCS12 schemas */ - ret = - _gnutls_pkcs12_string_to_key (1 /*KEY*/, kdf_params->salt, + if (ret < 0) + { + gnutls_assert (); + return ret; + } + } + break; + + default: + ret = + _gnutls_pkcs12_string_to_key (1 /*KEY*/, kdf_params->salt, kdf_params->salt_size, kdf_params->iter_count, password, kdf_params->key_size, key->data); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - /* Now generate the IV - */ - if (enc_params->iv_size) - { - ret = - _gnutls_pkcs12_string_to_key (2 /*IV*/, kdf_params->salt, + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + /* Now generate the IV + */ + if (enc_params->iv_size) + { + ret = + _gnutls_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); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - } + if (ret < 0) + { + gnutls_assert (); + return ret; + } + } } @@ -1869,70 +2009,74 @@ write_schema_params (schema_id schema, ASN1_TYPE pkcs8_asn, int result; ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY; - if (schema == PBES2) + switch(schema) { - if ((result = + case PBES2_3DES: + case PBES2_AES_128: + case PBES2_AES_192: + case PBES2_AES_256: + if ((result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.pkcs-5-PBES2-params", &pbes2_asn)) != ASN1_SUCCESS) - { - gnutls_assert (); - return _gnutls_asn2err (result); - } - - result = write_pbkdf2_params (pbes2_asn, kdf_params); - if (result < 0) - { - gnutls_assert (); - goto error; - } - - result = write_pbe_enc_params (pbes2_asn, enc_params); - if (result < 0) - { - gnutls_assert (); - goto error; - } - - result = _gnutls_x509_der_encode_and_copy (pbes2_asn, "", + { + gnutls_assert (); + return _gnutls_asn2err (result); + } + + result = write_pbkdf2_params (pbes2_asn, kdf_params); + if (result < 0) + { + gnutls_assert (); + goto error; + } + + result = write_pbe_enc_params (pbes2_asn, enc_params); + if (result < 0) + { + gnutls_assert (); + goto error; + } + + result = _gnutls_x509_der_encode_and_copy (pbes2_asn, "", pkcs8_asn, where, 0); - if (result < 0) - { - gnutls_assert (); - goto error; - } - - asn1_delete_structure (&pbes2_asn); - } - else - { /* PKCS12 schemas */ - - if ((result = + if (result < 0) + { + gnutls_assert (); + goto error; + } + + asn1_delete_structure (&pbes2_asn); + break; + + default: + + if ((result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.pkcs-12-PbeParams", &pbes2_asn)) != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto error; - } - - result = write_pkcs12_kdf_params (pbes2_asn, kdf_params); - if (result < 0) - { - gnutls_assert (); - goto error; - } - - result = _gnutls_x509_der_encode_and_copy (pbes2_asn, "", + { + gnutls_assert (); + result = _gnutls_asn2err (result); + goto error; + } + + result = write_pkcs12_kdf_params (pbes2_asn, kdf_params); + if (result < 0) + { + gnutls_assert (); + goto error; + } + + result = _gnutls_x509_der_encode_and_copy (pbes2_asn, "", pkcs8_asn, where, 0); - if (result < 0) - { - gnutls_assert (); - goto error; - } + if (result < 0) + { + gnutls_assert (); + goto error; + } - asn1_delete_structure (&pbes2_asn); + asn1_delete_structure (&pbes2_asn); } @@ -2086,7 +2230,7 @@ _gnutls_pkcs7_decrypt_data (const gnutls_datum_t * data, params_len = params_end - params_start + 1; result = - read_pkcs_schema_params (schema, password, + read_pkcs_schema_params (&schema, password, &data->data[params_start], params_len, &kdf_params, &enc_params); if (result < ASN1_SUCCESS) @@ -2152,7 +2296,10 @@ _gnutls_pkcs7_encrypt_data (schema_id schema, */ switch (schema) { - case PBES2: + case PBES2_3DES: + case PBES2_AES_128: + case PBES2_AES_192: + case PBES2_AES_256: result = asn1_write_value (pkcs7_asn, "encryptedContentInfo.contentEncryptionAlgorithm.algorithm", diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h index 5a1497a4cd..dac7b1f513 100644 --- a/lib/x509/x509_int.h +++ b/lib/x509/x509_int.h @@ -350,12 +350,17 @@ int _gnutls_pkcs7_decrypt_data (const gnutls_datum_t * data, typedef enum schema_id { - PBES2, /* the stuff in PKCS #5 */ + PBES2_GENERIC, /* when the algorithm is unknown, temporal use when reading only */ + PBES2_3DES, /* the stuff in PKCS #5 */ + PBES2_AES_128, + PBES2_AES_192, + PBES2_AES_256, PKCS12_3DES_SHA1, /* the stuff in PKCS #12 */ PKCS12_ARCFOUR_SHA1, PKCS12_RC2_40_SHA1 } schema_id; +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); diff --git a/src/certtool-gaa.c b/src/certtool-gaa.c index c2d955189e..951ec598eb 100644 --- a/src/certtool-gaa.c +++ b/src/certtool-gaa.c @@ -173,6 +173,7 @@ void gaa_help(void) __gaa_helpsingle(0, "outfile", "FILE ", "Output file."); __gaa_helpsingle(0, "infile", "FILE ", "Input file."); __gaa_helpsingle(0, "template", "FILE ", "Template file to use for non interactive operation."); + __gaa_helpsingle(0, "pkcs-cipher", "CIPHER ", "Cipher to use for pkcs operations (3des,aes-128,aes-192,aes-256,rc2-40)."); __gaa_helpsingle('d', "debug", "LEVEL ", "specify the debug level. Default is 1."); __gaa_helpsingle('h', "help", "", "shows this help text"); __gaa_helpsingle('v', "version", "", "shows the program's version"); @@ -190,8 +191,10 @@ typedef struct _gaainfo gaainfo; struct _gaainfo { -#line 125 "certtool.gaa" +#line 128 "certtool.gaa" int debug; +#line 124 "certtool.gaa" + char *pkcs_cipher; #line 121 "certtool.gaa" char *template; #line 118 "certtool.gaa" @@ -288,54 +291,55 @@ static int gaa_error = 0; #define GAA_MULTIPLE_OPTION 3 #define GAA_REST 0 -#define GAA_NB_OPTION 47 +#define GAA_NB_OPTION 48 #define GAAOPTID_version 1 #define GAAOPTID_help 2 #define GAAOPTID_debug 3 -#define GAAOPTID_template 4 -#define GAAOPTID_infile 5 -#define GAAOPTID_outfile 6 -#define GAAOPTID_disable_quick_random 7 -#define GAAOPTID_bits 8 -#define GAAOPTID_outraw 9 -#define GAAOPTID_outder 10 -#define GAAOPTID_inraw 11 -#define GAAOPTID_inder 12 -#define GAAOPTID_export_ciphers 13 -#define GAAOPTID_hash 14 -#define GAAOPTID_dsa 15 -#define GAAOPTID_pkcs8 16 -#define GAAOPTID_to_p8 17 -#define GAAOPTID_to_p12 18 -#define GAAOPTID_v1 19 -#define GAAOPTID_fix_key 20 -#define GAAOPTID_pgp_key_info 21 -#define GAAOPTID_key_info 22 -#define GAAOPTID_smime_to_p7 23 -#define GAAOPTID_p7_info 24 -#define GAAOPTID_p12_info 25 -#define GAAOPTID_crq_info 26 -#define GAAOPTID_crl_info 27 -#define GAAOPTID_pgp_ring_info 28 -#define GAAOPTID_pgp_certificate_info 29 -#define GAAOPTID_certificate_info 30 -#define GAAOPTID_password 31 -#define GAAOPTID_load_ca_certificate 32 -#define GAAOPTID_load_ca_privkey 33 -#define GAAOPTID_load_certificate 34 -#define GAAOPTID_load_request 35 -#define GAAOPTID_load_privkey 36 -#define GAAOPTID_get_dh_params 37 -#define GAAOPTID_generate_dh_params 38 -#define GAAOPTID_verify_crl 39 -#define GAAOPTID_verify_chain 40 -#define GAAOPTID_generate_request 41 -#define GAAOPTID_generate_privkey 42 -#define GAAOPTID_update_certificate 43 -#define GAAOPTID_generate_crl 44 -#define GAAOPTID_generate_proxy 45 -#define GAAOPTID_generate_certificate 46 -#define GAAOPTID_generate_self_signed 47 +#define GAAOPTID_pkcs_cipher 4 +#define GAAOPTID_template 5 +#define GAAOPTID_infile 6 +#define GAAOPTID_outfile 7 +#define GAAOPTID_disable_quick_random 8 +#define GAAOPTID_bits 9 +#define GAAOPTID_outraw 10 +#define GAAOPTID_outder 11 +#define GAAOPTID_inraw 12 +#define GAAOPTID_inder 13 +#define GAAOPTID_export_ciphers 14 +#define GAAOPTID_hash 15 +#define GAAOPTID_dsa 16 +#define GAAOPTID_pkcs8 17 +#define GAAOPTID_to_p8 18 +#define GAAOPTID_to_p12 19 +#define GAAOPTID_v1 20 +#define GAAOPTID_fix_key 21 +#define GAAOPTID_pgp_key_info 22 +#define GAAOPTID_key_info 23 +#define GAAOPTID_smime_to_p7 24 +#define GAAOPTID_p7_info 25 +#define GAAOPTID_p12_info 26 +#define GAAOPTID_crq_info 27 +#define GAAOPTID_crl_info 28 +#define GAAOPTID_pgp_ring_info 29 +#define GAAOPTID_pgp_certificate_info 30 +#define GAAOPTID_certificate_info 31 +#define GAAOPTID_password 32 +#define GAAOPTID_load_ca_certificate 33 +#define GAAOPTID_load_ca_privkey 34 +#define GAAOPTID_load_certificate 35 +#define GAAOPTID_load_request 36 +#define GAAOPTID_load_privkey 37 +#define GAAOPTID_get_dh_params 38 +#define GAAOPTID_generate_dh_params 39 +#define GAAOPTID_verify_crl 40 +#define GAAOPTID_verify_chain 41 +#define GAAOPTID_generate_request 42 +#define GAAOPTID_generate_privkey 43 +#define GAAOPTID_update_certificate 44 +#define GAAOPTID_generate_crl 45 +#define GAAOPTID_generate_proxy 46 +#define GAAOPTID_generate_certificate 47 +#define GAAOPTID_generate_self_signed 48 #line 168 "gaa.skel" @@ -495,12 +499,31 @@ static int gaa_getint(char *arg) return tmp; } +static char gaa_getchar(char *arg) +{ + if(strlen(arg) != 1) + { + printf("Option %s: '%s' isn't an character\n", gaa_current_option, arg); + GAAERROR(-1); + } + return arg[0]; +} static char* gaa_getstr(char *arg) { return arg; } - +static float gaa_getfloat(char *arg) +{ + float tmp; + char a; + if(sscanf(arg, "%f%c", &tmp, &a) < 1) + { + printf("Option %s: '%s' isn't a float number\n", gaa_current_option, arg); + GAAERROR(-1); + } + return tmp; +} /* option structures */ struct GAAOPTION_debug @@ -509,6 +532,12 @@ struct GAAOPTION_debug int size1; }; +struct GAAOPTION_pkcs_cipher +{ + char* arg1; + int size1; +}; + struct GAAOPTION_template { char* arg1; @@ -605,6 +634,7 @@ static int gaa_get_option_num(char *str, int status) { case GAA_LETTER_OPTION: GAA_CHECK1STR("d", GAAOPTID_debug); + GAA_CHECK1STR("", GAAOPTID_pkcs_cipher); GAA_CHECK1STR("", GAAOPTID_template); GAA_CHECK1STR("", GAAOPTID_infile); GAA_CHECK1STR("", GAAOPTID_outfile); @@ -660,6 +690,7 @@ static int gaa_get_option_num(char *str, int status) GAA_CHECKSTR("version", GAAOPTID_version); GAA_CHECKSTR("help", GAAOPTID_help); GAA_CHECKSTR("debug", GAAOPTID_debug); + GAA_CHECKSTR("pkcs-cipher", GAAOPTID_pkcs_cipher); GAA_CHECKSTR("template", GAAOPTID_template); GAA_CHECKSTR("infile", GAAOPTID_infile); GAA_CHECKSTR("outfile", GAAOPTID_outfile); @@ -717,6 +748,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) int OK = 0; int gaa_last_non_option; struct GAAOPTION_debug GAATMP_debug; + struct GAAOPTION_pkcs_cipher GAATMP_pkcs_cipher; struct GAAOPTION_template GAATMP_template; struct GAAOPTION_infile GAATMP_infile; struct GAAOPTION_outfile GAATMP_outfile; @@ -750,14 +782,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) { case GAAOPTID_version: OK = 0; -#line 130 "certtool.gaa" +#line 133 "certtool.gaa" { certtool_version(); exit(0); ;}; return GAA_OK; break; case GAAOPTID_help: OK = 0; -#line 128 "certtool.gaa" +#line 131 "certtool.gaa" { gaa_help(); exit(0); ;}; return GAA_OK; @@ -767,11 +799,21 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_debug.arg1, gaa_getint, GAATMP_debug.size1); gaa_index++; -#line 126 "certtool.gaa" +#line 129 "certtool.gaa" { gaaval->debug = GAATMP_debug.arg1 ;}; return GAA_OK; break; + case GAAOPTID_pkcs_cipher: + OK = 0; + GAA_TESTMOREARGS; + GAA_FILL(GAATMP_pkcs_cipher.arg1, gaa_getstr, GAATMP_pkcs_cipher.size1); + gaa_index++; +#line 125 "certtool.gaa" +{ gaaval->pkcs_cipher = GAATMP_pkcs_cipher.arg1 ;}; + + return GAA_OK; + break; case GAAOPTID_template: OK = 0; GAA_TESTMOREARGS; @@ -1123,29 +1165,26 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) int gaa(int argc, char **argv, gaainfo *gaaval) { int tmp1, tmp2; - int l; - size_t i, j; + int i, j; char *opt_list; - i = 0; - GAAargv = argv; GAAargc = argc; opt_list = (char*) gaa_malloc(GAA_NB_OPTION + 1); - for(l = 0; l < GAA_NB_OPTION + 1; l++) - opt_list[l] = 0; + for(i = 0; i < GAA_NB_OPTION + 1; i++) + opt_list[i] = 0; /* initialization */ if(inited == 0) { -#line 132 "certtool.gaa" +#line 135 "certtool.gaa" { gaaval->bits = 2048; gaaval->pkcs8 = 0; gaaval->privkey = NULL; gaaval->ca=NULL; gaaval->ca_privkey = NULL; gaaval->debug=1; gaaval->request = NULL; gaaval->infile = NULL; gaaval->outfile = NULL; gaaval->cert = NULL; gaaval->incert_format = 0; gaaval->outcert_format = 0; gaaval->action=-1; gaaval->pass = NULL; gaaval->v1_cert = 0; gaaval->export = 0; gaaval->template = NULL; gaaval->hash=NULL; gaaval->fix_key = 0; gaaval->quick_random=1; - gaaval->privkey_op = 0; ;}; + gaaval->privkey_op = 0; gaaval->pkcs_cipher = "3des"; ;}; } inited = 1; @@ -1156,27 +1195,27 @@ int gaa(int argc, char **argv, gaainfo *gaaval) gaa_arg_used = gaa_malloc(argc * sizeof(char)); } - for(l = 1; l < argc; l++) - gaa_arg_used[l] = 0; - for(l = 1; l < argc; l++) + for(i = 1; i < argc; i++) + gaa_arg_used[i] = 0; + for(i = 1; i < argc; i++) { - if(gaa_arg_used[l] == 0) + if(gaa_arg_used[i] == 0) { j = 0; - tmp1 = gaa_is_an_argument(GAAargv[l]); + tmp1 = gaa_is_an_argument(GAAargv[i]); switch(tmp1) { case GAA_WORD_OPTION: j++; case GAA_LETTER_OPTION: j++; - tmp2 = gaa_get_option_num(argv[l]+j, tmp1); + tmp2 = gaa_get_option_num(argv[i]+j, tmp1); if(tmp2 == GAA_ERROR_NOMATCH) { - printf("Invalid option '%s'\n", argv[l]+j); + printf("Invalid option '%s'\n", argv[i]+j); return 0; } - switch(gaa_try(tmp2, l+1, gaaval, opt_list)) + switch(gaa_try(tmp2, i+1, gaaval, opt_list)) { case GAA_ERROR_NOTENOUGH_ARGS: printf("'%s': not enough arguments\n",gaa_current_option); @@ -1189,18 +1228,18 @@ int gaa(int argc, char **argv, gaainfo *gaaval) default: printf("Unknown error\n"); } - gaa_arg_used[l] = 1; + gaa_arg_used[i] = 1; break; case GAA_MULTIPLE_OPTION: - for(j = 1; j < strlen(argv[l]); j++) + for(j = 1; j < strlen(argv[i]); j++) { - tmp2 = gaa_get_option_num(argv[l]+j, tmp1); + tmp2 = gaa_get_option_num(argv[i]+j, tmp1); if(tmp2 == GAA_ERROR_NOMATCH) { - printf("Invalid option '%c'\n", *(argv[l]+j)); + printf("Invalid option '%c'\n", *(argv[i]+j)); return 0; } - switch(gaa_try(tmp2, l+1, gaaval, opt_list)) + switch(gaa_try(tmp2, i+1, gaaval, opt_list)) { case GAA_ERROR_NOTENOUGH_ARGS: printf("'%s': not enough arguments\n",gaa_current_option); @@ -1214,7 +1253,7 @@ int gaa(int argc, char **argv, gaainfo *gaaval) printf("Unknown error\n"); } } - gaa_arg_used[l] = 1; + gaa_arg_used[i] = 1; break; default: break; } @@ -1240,9 +1279,9 @@ if(gaa_processing_file == 0) } #endif } - for(l = 1; l < argc; l++) + for(i = 1; i < argc; i++) { - if(gaa_arg_used[l] == 0) + if(gaa_arg_used[i] == 0) { printf("Too many arguments\n"); return 0; @@ -1293,7 +1332,7 @@ static int gaa_internal_get_next_str(FILE *file, gaa_str_node *tmp_str, int argc len++; a = fgetc( file); - if(a==EOF) return 0; /* a = ' '; */ + if(a==EOF) return 0; //a = ' '; } len += 1; diff --git a/src/certtool-gaa.h b/src/certtool-gaa.h index 42181c5d8a..bfd3bf4533 100644 --- a/src/certtool-gaa.h +++ b/src/certtool-gaa.h @@ -8,8 +8,10 @@ typedef struct _gaainfo gaainfo; struct _gaainfo { -#line 125 "certtool.gaa" +#line 128 "certtool.gaa" int debug; +#line 124 "certtool.gaa" + char *pkcs_cipher; #line 121 "certtool.gaa" char *template; #line 118 "certtool.gaa" diff --git a/src/certtool.c b/src/certtool.c index c1f41345dd..ae61a8e674 100644 --- a/src/certtool.c +++ b/src/certtool.c @@ -2416,6 +2416,28 @@ verify_crl (void) fprintf (outfile, "\n"); } +static int cipher_to_flags(const char* cipher) +{ +int flags; + + if (strcasecmp(cipher, "3des")==0) { + flags = GNUTLS_PKCS_USE_PBES2_3DES; + } else if (strcasecmp(cipher, "aes-128")==0) { + flags = GNUTLS_PKCS_USE_PBES2_AES_128; + } else if (strcasecmp(cipher, "aes-192")==0) { + flags = GNUTLS_PKCS_USE_PBES2_AES_192; + } else if (strcasecmp(cipher, "aes-256")==0) { + flags = GNUTLS_PKCS_USE_PBES2_AES_256; + } else if (strcasecmp(cipher, "rc2-40")==0) { + flags = GNUTLS_PKCS_USE_PKCS12_RC2_40; + } else { + error(EXIT_FAILURE, 0, "Unknown cipher %s\n", cipher); + } + + return flags; + +} + void generate_pkcs8 (void) { @@ -2437,7 +2459,7 @@ generate_pkcs8 (void) if (info.export) flags = GNUTLS_PKCS_USE_PKCS12_RC2_40; else - flags = GNUTLS_PKCS_USE_PKCS12_3DES; + flags = cipher_to_flags(info.pkcs_cipher); if (password == NULL || password[0] == 0) { @@ -2530,7 +2552,7 @@ generate_pkcs12 (void) if (info.export) flags = GNUTLS_PKCS_USE_PKCS12_RC2_40; else - flags = GNUTLS_PKCS8_USE_PKCS12_3DES; + flags = cipher_to_flags(info.pkcs_cipher); result = gnutls_pkcs12_bag_encrypt (bag, pass, flags); if (result < 0) @@ -2552,7 +2574,7 @@ generate_pkcs12 (void) if (info.export) flags = GNUTLS_PKCS_USE_PKCS12_RC2_40; else - flags = GNUTLS_PKCS_USE_PKCS12_3DES; + flags = cipher_to_flags(info.pkcs_cipher); size = sizeof (buffer); result = diff --git a/src/certtool.gaa b/src/certtool.gaa index 965dfd3ff7..411edcf743 100644 --- a/src/certtool.gaa +++ b/src/certtool.gaa @@ -121,6 +121,9 @@ option (infile) STR "FILE" { $infile = $1 } "Input file." #char *template; option (template) STR "FILE" { $template = $1 } "Template file to use for non interactive operation." +#char *pkcs_cipher; +option (pkcs-cipher) STR "CIPHER" { $pkcs_cipher = $1 } "Cipher to use for pkcs operations (3des,aes-128,aes-192,aes-256,rc2-40)." + #int debug; option (d, debug) INT "LEVEL" { $debug = $1 } "specify the debug level. Default is 1." @@ -133,5 +136,5 @@ init { $bits = 2048; $pkcs8 = 0; $privkey = NULL; $ca=NULL; $ca_privkey = NULL; $debug=1; $request = NULL; $infile = NULL; $outfile = NULL; $cert = NULL; $incert_format = 0; $outcert_format = 0; $action=-1; $pass = NULL; $v1_cert = 0; $export = 0; $template = NULL; $hash=NULL; $fix_key = 0; $quick_random=1; - $privkey_op = 0; } + $privkey_op = 0; $pkcs_cipher = "3des"; } |