static void write_header( cipher_filter_context_t *cfx, IOBUF a ) { PACKET pkt; PKT_encrypted ed; byte temp[18]; unsigned blocksize; unsigned nprefix; blocksize = cipher_get_blocksize( cfx->dek->algo ); if( blocksize < 8 || blocksize > 16 ) log_fatal("unsupported blocksize %u\n", blocksize ); memset( &ed, 0, sizeof ed ); ed.len = cfx->datalen; ed.extralen = blocksize+2; ed.new_ctb = !ed.len && !RFC1991; if( cfx->dek->use_mdc ) { ed.mdc_method = DIGEST_ALGO_SHA1; cfx->mdc_hash = md_open( DIGEST_ALGO_SHA1, 0 ); if ( DBG_HASHING ) md_start_debug( cfx->mdc_hash, "creatmdc" ); } { char buf[20]; sprintf (buf, "%d %d", ed.mdc_method, cfx->dek->algo); write_status_text (STATUS_BEGIN_ENCRYPTION, buf); } init_packet( &pkt ); pkt.pkttype = cfx->dek->use_mdc? PKT_ENCRYPTED_MDC : PKT_ENCRYPTED; pkt.pkt.encrypted = &ed; if( build_packet( a, &pkt )) log_bug("build_packet(ENCR_DATA) failed\n"); nprefix = blocksize; randomize_buffer( temp, nprefix, 1 ); temp[nprefix] = temp[nprefix-2]; temp[nprefix+1] = temp[nprefix-1]; print_cipher_algo_note( cfx->dek->algo ); cfx->cipher_hd = cipher_open( cfx->dek->algo, cfx->dek->use_mdc? CIPHER_MODE_CFB : CIPHER_MODE_AUTO_CFB, 1 ); /* log_hexdump( "thekey", cfx->dek->key, cfx->dek->keylen );*/ cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen ); cipher_setiv( cfx->cipher_hd, NULL, 0 ); /* log_hexdump( "prefix", temp, nprefix+2 ); */ if( cfx->mdc_hash ) /* hash the "IV" */ md_write( cfx->mdc_hash, temp, nprefix+2 ); cipher_encrypt( cfx->cipher_hd, temp, temp, nprefix+2); cipher_sync( cfx->cipher_hd ); iobuf_write(a, temp, nprefix+2); cfx->header=1; }
static void write_header (cipher_filter_context_t *cfx, iobuf_t a) { gcry_error_t err; PACKET pkt; PKT_encrypted ed; byte temp[18]; unsigned int blocksize; unsigned int nprefix; blocksize = openpgp_cipher_get_algo_blklen (cfx->dek->algo); if ( blocksize < 8 || blocksize > 16 ) log_fatal ("unsupported blocksize %u\n", blocksize); memset (&ed, 0, sizeof ed); ed.len = cfx->datalen; ed.extralen = blocksize + 2; ed.new_ctb = !ed.len; if (cfx->dek->use_mdc) { ed.mdc_method = DIGEST_ALGO_SHA1; gcry_md_open (&cfx->mdc_hash, DIGEST_ALGO_SHA1, 0); if (DBG_HASHING) gcry_md_debug (cfx->mdc_hash, "creatmdc"); } else if (!opt.no_mdc_warn) { log_info ("WARNING: " "encrypting without integrity protection is dangerous\n"); } write_status_printf (STATUS_BEGIN_ENCRYPTION, "%d %d", ed.mdc_method, cfx->dek->algo); init_packet (&pkt); pkt.pkttype = cfx->dek->use_mdc? PKT_ENCRYPTED_MDC : PKT_ENCRYPTED; pkt.pkt.encrypted = &ed; if (build_packet( a, &pkt)) log_bug ("build_packet(ENCR_DATA) failed\n"); nprefix = blocksize; gcry_randomize (temp, nprefix, GCRY_STRONG_RANDOM ); temp[nprefix] = temp[nprefix-2]; temp[nprefix+1] = temp[nprefix-1]; print_cipher_algo_note (cfx->dek->algo); err = openpgp_cipher_open (&cfx->cipher_hd, cfx->dek->algo, GCRY_CIPHER_MODE_CFB, (GCRY_CIPHER_SECURE | ((cfx->dek->use_mdc || cfx->dek->algo >= 100)? 0 : GCRY_CIPHER_ENABLE_SYNC))); if (err) { /* We should never get an error here cause we already checked, * that the algorithm is available. */ BUG(); } /* log_hexdump ("thekey", cfx->dek->key, cfx->dek->keylen); */ gcry_cipher_setkey (cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen); gcry_cipher_setiv (cfx->cipher_hd, NULL, 0); /* log_hexdump ("prefix", temp, nprefix+2); */ if (cfx->mdc_hash) /* Hash the "IV". */ gcry_md_write (cfx->mdc_hash, temp, nprefix+2 ); gcry_cipher_encrypt (cfx->cipher_hd, temp, nprefix+2, NULL, 0); gcry_cipher_sync (cfx->cipher_hd); iobuf_write (a, temp, nprefix+2); cfx->short_blklen_warn = (blocksize < 16); cfx->short_blklen_count = nprefix+2; cfx->wrote_header = 1; }
/**************** * Protect the secret key with the passphrase from DEK */ int protect_secret_key( PKT_secret_key *sk, DEK *dek ) { int i,j, rc = 0; byte *buffer; size_t nbytes; u16 csum; if( !dek ) return 0; if( !sk->is_protected ) { /* okay, apply the protection */ gcry_cipher_hd_t cipher_hd=NULL; if ( openpgp_cipher_test_algo ( sk->protect.algo ) ) { /* Unsupport protection algorithm. */ rc = gpg_error (GPG_ERR_CIPHER_ALGO); } else { print_cipher_algo_note( sk->protect.algo ); if ( openpgp_cipher_open (&cipher_hd, sk->protect.algo, GCRY_CIPHER_MODE_CFB, (GCRY_CIPHER_SECURE | (sk->protect.algo >= 100 ? 0 : GCRY_CIPHER_ENABLE_SYNC))) ) BUG(); if ( gcry_cipher_setkey ( cipher_hd, dek->key, dek->keylen ) ) log_info(_("WARNING: Weak key detected" " - please change passphrase again.\n")); sk->protect.ivlen = openpgp_cipher_get_algo_blklen (sk->protect.algo); assert( sk->protect.ivlen <= DIM(sk->protect.iv) ); if( sk->protect.ivlen != 8 && sk->protect.ivlen != 16 ) BUG(); /* yes, we are very careful */ gcry_create_nonce (sk->protect.iv, sk->protect.ivlen); gcry_cipher_setiv (cipher_hd, sk->protect.iv, sk->protect.ivlen); if( sk->version >= 4 ) { byte *bufarr[PUBKEY_MAX_NSKEY]; size_t narr[PUBKEY_MAX_NSKEY]; unsigned int nbits[PUBKEY_MAX_NSKEY]; int ndata=0; byte *p, *data; for (j=0, i = pubkey_get_npkey(sk->pubkey_algo); i < pubkey_get_nskey(sk->pubkey_algo); i++, j++ ) { assert (!gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE)); if (gcry_mpi_aprint (GCRYMPI_FMT_USG, bufarr+j, narr+j, sk->skey[i])) BUG(); nbits[j] = gcry_mpi_get_nbits (sk->skey[i]); ndata += narr[j] + 2; } for ( ; j < PUBKEY_MAX_NSKEY; j++ ) bufarr[j] = NULL; ndata += opt.simple_sk_checksum? 2 : 20; /* for checksum */ data = xmalloc_secure( ndata ); p = data; for(j=0; j < PUBKEY_MAX_NSKEY && bufarr[j]; j++ ) { p[0] = nbits[j] >> 8 ; p[1] = nbits[j]; p += 2; memcpy(p, bufarr[j], narr[j] ); p += narr[j]; xfree(bufarr[j]); } if (opt.simple_sk_checksum) { log_info (_("generating the deprecated 16-bit checksum" " for secret key protection\n")); csum = checksum( data, ndata-2); sk->csum = csum; *p++ = csum >> 8; *p++ = csum; sk->protect.sha1chk = 0; } else {