guchar* gkm_data_der_write_private_pkcs8_crypted (gcry_sexp_t skey, const gchar *password, gsize n_password, gsize *n_data) { gcry_error_t gcry; gcry_cipher_hd_t cih; GNode *asn = NULL; guchar *key, *data; gsize n_key, block = 0; /* Encode the key in normal pkcs8 fashion */ key = gkm_data_der_write_private_pkcs8_plain (skey, &n_key); if (key == NULL) return NULL; asn = egg_asn1x_create (pkix_asn1_tab, "pkcs-8-EncryptedPrivateKeyInfo"); g_return_val_if_fail (asn, NULL); /* Create a and write out a cipher used for encryption */ cih = prepare_and_encode_pkcs8_cipher (asn, password, n_password, &block); g_return_val_if_fail (cih, NULL); /* Pad the block of data */ if(block > 1) { gsize pad; guchar *padded; pad = block - (n_key % block); if (pad == 0) pad = block; padded = egg_secure_realloc (key, n_key + pad); memset (padded + n_key, pad, pad); key = padded; n_key += pad; } gcry = gcry_cipher_encrypt (cih, key, n_key, NULL, 0); g_return_val_if_fail (gcry == 0, NULL); gcry_cipher_close (cih); if (!egg_asn1x_set_string_as_raw (egg_asn1x_node (asn, "encryptedData", NULL), key, n_key, egg_secure_free)) g_return_val_if_reached (NULL); data = egg_asn1x_encode (asn, NULL, n_data); if (data == NULL) g_warning ("couldn't encode encrypted pkcs8 key: %s", egg_asn1x_message (asn)); egg_asn1x_destroy (asn); return data; }
static gcry_cipher_hd_t prepare_and_encode_pkcs8_cipher (GNode *asn, const gchar *password, gsize n_password, gsize *n_block) { GNode *asn1_params = NULL; gcry_cipher_hd_t cih; guchar salt[8]; gcry_error_t gcry; guchar *key, *iv, *portion; gsize n_key, n_portion; int iterations; init_quarks (); /* Make sure the encryption algorithm works */ g_return_val_if_fail (gcry_cipher_algo_info (OID_PKCS12_PBE_3DES_SHA1, GCRYCTL_TEST_ALGO, NULL, 0), NULL); /* The encryption algorithm */ if(!egg_asn1x_set_oid_as_quark (egg_asn1x_node (asn, "encryptionAlgorithm", "algorithm", NULL), OID_PKCS12_PBE_3DES_SHA1)) g_return_val_if_reached (NULL); /* Randomize some input for the password based secret */ iterations = 1000 + (int) (1000.0 * rand () / (RAND_MAX + 1.0)); gcry_create_nonce (salt, sizeof (salt)); /* Allocate space for the key and iv */ n_key = gcry_cipher_get_algo_keylen (GCRY_CIPHER_3DES); *n_block = gcry_cipher_get_algo_blklen (GCRY_MD_SHA1); g_return_val_if_fail (n_key && *n_block, NULL); if (!egg_symkey_generate_pkcs12 (GCRY_CIPHER_3DES, GCRY_MD_SHA1, password, n_password, salt, sizeof (salt), iterations, &key, &iv)) g_return_val_if_reached (NULL); /* Now write out the parameters */ asn1_params = egg_asn1x_create (pkix_asn1_tab, "pkcs-12-PbeParams"); g_return_val_if_fail (asn1_params, NULL); if (!egg_asn1x_set_string_as_raw (egg_asn1x_node (asn1_params, "salt", NULL), salt, sizeof (salt), NULL)) g_return_val_if_reached (NULL); if (!egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn1_params, "iterations", NULL), iterations)) g_return_val_if_reached (NULL); portion = egg_asn1x_encode (asn1_params, NULL, &n_portion); if (portion == NULL) { g_warning ("couldn't encode pkcs8 params key: %s", egg_asn1x_message (asn1_params)); g_return_val_if_reached (NULL); } if (!egg_asn1x_set_raw_element (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL), portion, n_portion, g_free)) g_return_val_if_reached (NULL); /* Now make a cipher that matches what we wrote out */ gcry = gcry_cipher_open (&cih, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0); g_return_val_if_fail (gcry == 0, NULL); g_return_val_if_fail (cih, NULL); gcry_cipher_setiv (cih, iv, *n_block); gcry_cipher_setkey (cih, key, n_key); g_free (iv); egg_secure_free (key); egg_asn1x_destroy (asn1_params); return cih; }
guchar* gkm_data_der_write_private_pkcs8_plain (gcry_sexp_t skey, gsize *n_data) { GNode *asn = NULL; int algorithm; gboolean is_priv; GQuark oid; guchar *params, *key, *data; gsize n_params, n_key; init_quarks (); /* Parse and check that the key is for real */ if (!gkm_sexp_parse_key (skey, &algorithm, &is_priv, NULL)) g_return_val_if_reached (NULL); g_return_val_if_fail (is_priv == TRUE, NULL); asn = egg_asn1x_create (pkix_asn1_tab, "pkcs-8-PrivateKeyInfo"); g_return_val_if_fail (asn, NULL); /* Write out the version */ if (!egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), 0)) g_return_val_if_reached (NULL); /* Per algorithm differences */ switch (algorithm) { /* RSA gets encoded in a standard simple way */ case GCRY_PK_RSA: oid = OID_PKIX1_RSA; params = NULL; n_params = 0; key = gkm_data_der_write_private_key_rsa (skey, &n_key); break; /* DSA gets incoded with the params seperate */ case GCRY_PK_DSA: oid = OID_PKIX1_DSA; key = gkm_data_der_write_private_key_dsa_part (skey, &n_key); params = gkm_data_der_write_private_key_dsa_params (skey, &n_params); break; default: g_warning ("trying to serialize unsupported private key algorithm: %d", algorithm); return NULL; }; /* Write out the algorithm */ if (!egg_asn1x_set_oid_as_quark (egg_asn1x_node (asn, "privateKeyAlgorithm", "algorithm", NULL), oid)) g_return_val_if_reached (NULL); /* Write out the parameters */ if (params) { if (!egg_asn1x_set_raw_element (egg_asn1x_node (asn, "privateKeyAlgorithm", "parameters", NULL), params, n_params, egg_secure_free)) g_return_val_if_reached (NULL); } /* Write out the key portion */ if (!egg_asn1x_set_string_as_raw (egg_asn1x_node (asn, "privateKey", NULL), key, n_key, egg_secure_free)) g_return_val_if_reached (NULL); data = egg_asn1x_encode (asn, egg_secure_realloc, n_data); if (data == NULL) g_warning ("couldn't encode private pkcs8 key: %s", egg_asn1x_message (asn)); egg_asn1x_destroy (asn); return data; }
static gcry_cipher_hd_t prepare_and_encode_pkcs8_cipher (GNode *asn, const gchar *password, gsize n_password, gsize *n_block) { GNode *asn1_params = NULL; gcry_cipher_hd_t cih; guchar *salt; gsize n_salt; gcry_error_t gcry; guchar *key, *iv; gsize n_key; int iterations; init_quarks (); /* Make sure the encryption algorithm works */ g_return_val_if_fail (gcry_cipher_algo_info (gcry_cipher_map_name (g_quark_to_string (OID_PKCS12_PBE_3DES_SHA1)), GCRYCTL_TEST_ALGO, NULL, 0) == 0, NULL); /* The encryption algorithm */ if(!egg_asn1x_set_oid_as_quark (egg_asn1x_node (asn, "encryptionAlgorithm", "algorithm", NULL), OID_PKCS12_PBE_3DES_SHA1)) g_return_val_if_reached (NULL); /* Randomize some input for the password based secret */ iterations = g_random_int_range (1000, 4096); n_salt = 8; salt = g_malloc (n_salt); gcry_create_nonce (salt, n_salt); /* Allocate space for the key and iv */ n_key = gcry_cipher_get_algo_keylen (GCRY_CIPHER_3DES); *n_block = gcry_cipher_get_algo_blklen (GCRY_MD_SHA1); g_return_val_if_fail (n_key && *n_block, NULL); if (!egg_symkey_generate_pkcs12 (GCRY_CIPHER_3DES, GCRY_MD_SHA1, password, n_password, salt, sizeof (salt), iterations, &key, &iv)) g_return_val_if_reached (NULL); /* Now write out the parameters */ asn1_params = egg_asn1x_create (pkix_asn1_tab, "pkcs-12-PbeParams"); g_return_val_if_fail (asn1_params, NULL); egg_asn1x_set_string_as_raw (egg_asn1x_node (asn1_params, "salt", NULL), salt, n_salt, g_free); egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn1_params, "iterations", NULL), iterations); egg_asn1x_set_any_from (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL), asn1_params); /* Now make a cipher that matches what we wrote out */ gcry = gcry_cipher_open (&cih, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0); g_return_val_if_fail (gcry == 0, NULL); g_return_val_if_fail (cih, NULL); gcry_cipher_setiv (cih, iv, *n_block); gcry_cipher_setkey (cih, key, n_key); g_free (iv); egg_secure_free (key); egg_asn1x_destroy (asn1_params); return cih; }