static void free_symkey_enc (cdk_pkt_symkey_enc_t enc) { if (!enc) return; cdk_s2k_free (enc->s2k); cdk_free (enc); }
void cdk_sk_release(cdk_seckey_t sk) { size_t nskey; if (!sk) return; nskey = cdk_pk_get_nskey(sk->pubkey_algo); _cdk_free_mpibuf(nskey, sk->mpi); cdk_free(sk->encdata); sk->encdata = NULL; cdk_pk_release(sk->pk); sk->pk = NULL; cdk_s2k_free(sk->protect.s2k); sk->protect.s2k = NULL; cdk_free(sk); }
/** * cdk_sk_protect: * @sk: the secret key * @pw: the passphrase to use * * Protect the given secret key with a passphrase. **/ cdk_error_t cdk_sk_protect (cdk_pkt_seckey_t sk, const char *pw) { gcry_cipher_hd_t hd = NULL; cdk_dek_t dek = NULL; cdk_s2k_t s2k; byte *p = NULL, buf[MAX_MPI_BYTES+2]; size_t enclen = 0, nskey, i, nbytes; size_t dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1); gcry_error_t err; cdk_error_t rc; nskey = cdk_pk_get_nskey (sk->pubkey_algo); if (!nskey) return CDK_Inv_Algo; rc = cdk_s2k_new (&s2k, CDK_S2K_ITERSALTED, GCRY_MD_SHA256, NULL); if (!rc) rc = cdk_dek_from_passphrase (&dek, GCRY_CIPHER_AES, s2k, 1, pw); if (rc) { cdk_s2k_free (s2k); return rc; } for (i = 0; i < nskey; i++) { enclen += 2; enclen += (gcry_mpi_get_nbits (sk->mpi[i])+7)/8; } p = sk->encdata = cdk_calloc (1, enclen + dlen + 1); if (!p) { cdk_s2k_free (s2k); return CDK_Out_Of_Core; } enclen = 0; for (i = 0; i < nskey; i++) { if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, DIM (buf), &nbytes, sk->mpi[i])) { cdk_free (p); cdk_s2k_free (s2k); return CDK_Wrong_Format; } memcpy (p + enclen, buf, nbytes); enclen += nbytes; } enclen += dlen; sk->enclen = enclen; sk->protect.s2k = s2k; sk->protect.algo = GCRY_CIPHER_AES; sk->protect.ivlen = gcry_cipher_get_algo_blklen (sk->protect.algo); gcry_randomize (sk->protect.iv, sk->protect.ivlen, GCRY_STRONG_RANDOM); err = gcry_cipher_open (&hd, sk->protect.algo, GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_ENABLE_SYNC); if (err) { cdk_dek_free (dek); rc = map_gcry_error (err); goto leave; } err = gcry_cipher_setkey (hd, dek->key, dek->keylen); if (!err) err = gcry_cipher_setiv (hd, sk->protect.iv, sk->protect.ivlen); cdk_dek_free (dek); if (err) { rc = map_gcry_error (err); goto leave; } sk->protect.sha1chk = 1; sk->is_protected = 1; sk->csum = 0; gcry_md_hash_buffer (GCRY_MD_SHA1, buf, p, enclen-dlen); memcpy (p + enclen - dlen, buf, dlen); gcry_cipher_encrypt (hd, p, enclen, NULL, 0); /* FIXME: We should release all MPI's and set the elements to NULL. */ leave: gcry_cipher_close (hd); return rc; }