- memset(tmp, 0, sizeof(tmp));
- memset(keymat, 0, sizeof(keymat));
-
- /* Private key files without the specific magic number are assumed
- to be the old-style private keys that are not encrypted. */
- SILC_GET32_MSB(magic, data);
- if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
- SILC_LOG_DEBUG(("Private key does not have correct magic!"));
-
- /* Now decode the actual private key */
- if (!silc_pkcs_private_key_decode(data, len, private_key)) {
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
-
- memset(old, 0, data_len);
- silc_free(old);
- return TRUE;
- }
-
- /* Allocate the AES cipher */
- if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
- SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
- blocklen = silc_cipher_get_block_len(aes);
- if (blocklen * 2 > sizeof(tmp)) {
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
-
- /* Allocate SHA1 hash */
- if (!silc_hash_alloc("sha1", &sha1)) {
- SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
- silc_cipher_free(aes);
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
-
- /* Allocate HMAC */
- if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
- SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
- silc_hash_free(sha1);
- silc_cipher_free(aes);
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
-
- /* Derive the decryption key from the provided key material. The key
- is 256 bits length, and derived by taking hash of the data, then
- re-hashing the data and the previous digest, and using the first and
- second digest as the key. */
- silc_hash_init(sha1);
- silc_hash_update(sha1, passphrase, passphrase_len);
- silc_hash_final(sha1, keymat);
- silc_hash_init(sha1);
- silc_hash_update(sha1, passphrase, passphrase_len);
- silc_hash_update(sha1, keymat, 16);
- silc_hash_final(sha1, keymat + 16);
-
- /* Set the key to the cipher */
- silc_cipher_set_key(aes, keymat, 256);
-
- /* First, verify the MAC of the private key data */
- mac_len = silc_hmac_len(sha1hmac);
- silc_hmac_init_with_key(sha1hmac, keymat, 16);
- silc_hmac_update(sha1hmac, data, len - mac_len);
- silc_hmac_final(sha1hmac, tmp, NULL);
- if (memcmp(tmp, data + (len - mac_len), mac_len)) {
- SILC_LOG_DEBUG(("Integrity check for private key failed"));
- memset(keymat, 0, sizeof(keymat));
- memset(tmp, 0, sizeof(tmp));
- silc_hmac_free(sha1hmac);
- silc_hash_free(sha1);
- silc_cipher_free(aes);
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
- data += 4;
- len -= 4;
-
- /* Decrypt the private key buffer */
- silc_cipher_decrypt(aes, data, data, len - mac_len, NULL);
- SILC_GET32_MSB(i, data);
- if (i > len) {
- SILC_LOG_DEBUG(("Bad private key length in buffer!"));
- memset(keymat, 0, sizeof(keymat));
- memset(tmp, 0, sizeof(tmp));
- silc_hmac_free(sha1hmac);
- silc_hash_free(sha1);
- silc_cipher_free(aes);
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
- data += 4;
- len = i;
-
- /* Cleanup */
- memset(keymat, 0, sizeof(keymat));
- memset(tmp, 0, sizeof(tmp));
- silc_hmac_free(sha1hmac);
- silc_hash_free(sha1);
- silc_cipher_free(aes);
-
- /* Now decode the actual private key */
- if (!silc_pkcs_private_key_decode(data, len, private_key)) {
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
-
- memset(old, 0, data_len);
- silc_free(old);