/** * cdk_stream_kick_off: * @inp: the input stream * @out: the output stream. * * Passes the entire data from @inp into the output stream @out * with all the activated filters. */ cdk_error_t cdk_stream_kick_off (cdk_stream_t inp, cdk_stream_t out) { byte buf[BUFSIZE]; int nread, nwritten; cdk_error_t rc; if (!inp || !out) { gnutls_assert (); return CDK_Inv_Value; } rc = CDK_Success; while (!cdk_stream_eof (inp)) { nread = cdk_stream_read (inp, buf, DIM (buf)); if (!nread || nread == EOF) break; nwritten = cdk_stream_write (out, buf, nread); if (!nwritten || nwritten == EOF) { /* In case of errors, we leave the loop. */ rc = inp->error; break; } } wipemem (buf, sizeof (buf)); return rc; }
static cdk_error_t write_literal (cdk_stream_t out, cdk_pkt_literal_t pt, int old_ctb) { byte buf[BUFSIZE]; size_t size; cdk_error_t rc; assert (out); assert (pt); /* We consider a packet without a body as an invalid packet. At least one octet must be present. */ if (!pt->len) return CDK_Inv_Packet; if (DEBUG_PKT) _cdk_log_debug ("write_literal:\n"); size = 6 + pt->namelen + pt->len; rc = pkt_write_head (out, old_ctb, size, CDK_PKT_LITERAL); if (rc) return rc; rc = stream_putc (out, pt->mode); if (rc) return rc; rc = stream_putc (out, pt->namelen); if (rc) return rc; if (pt->namelen > 0) rc = stream_write (out, pt->name, pt->namelen); if (!rc) rc = write_32 (out, pt->timestamp); if (rc) return rc; while (!cdk_stream_eof (pt->buf) && !rc) { rc = stream_read (pt->buf, buf, DIM (buf), &size); if (!rc) rc = stream_write (out, buf, size); } wipemem (buf, sizeof (buf)); return rc; }
cdk_error_t cdk_stream_kick_off( cdk_stream_t inp, cdk_stream_t out ) { byte buf[8192]; int nread, nwritten; int rc = 0; if( !inp || !out ) return CDK_Inv_Value; while( !cdk_stream_eof( inp ) ) { nread = cdk_stream_read( inp, buf, sizeof buf-1 ); if( nread == EOF ) break; nwritten = cdk_stream_write( out, buf, nread ); if( nwritten == EOF ) rc = CDK_File_Error; } wipemem( buf, sizeof buf ); return rc; }
static int stream_cache_flush (cdk_stream_t s, FILE * fp) { int nwritten; assert (s); /* FIXME: We should find a way to use cdk_stream_write here. */ if (s->cache.size > 0) { nwritten = fwrite (s->cache.buf, 1, s->cache.size, fp); if (!nwritten) { gnutls_assert (); return CDK_File_Error; } s->cache.size = 0; s->cache.on = 0; wipemem (s->cache.buf, s->cache.alloced); } return 0; }
static cdk_error_t hash_encode (void *data, FILE * in, FILE * out) { md_filter_t *mfx = data; byte buf[BUFSIZE]; int err; int nread; if (!mfx) { gnutls_assert (); return CDK_Inv_Value; } _cdk_log_debug ("hash filter: encode algo=%d\n", mfx->digest_algo); if (!mfx->md_initialized) { err = _gnutls_hash_init (&mfx->md, mfx->digest_algo); if (err < 0) { gnutls_assert (); return map_gnutls_error (err); } mfx->md_initialized = 1; } while (!feof (in)) { nread = fread (buf, 1, BUFSIZE, in); if (!nread) break; _gnutls_hash (&mfx->md, buf, nread); } wipemem (buf, sizeof (buf)); return 0; }
/** * cdk_sk_unprotect: * @sk: the secret key * @pw: the passphrase * * Unprotect the given secret key with the passphrase. **/ cdk_error_t cdk_sk_unprotect (cdk_pkt_seckey_t sk, const char *pw) { gcry_cipher_hd_t hd; cdk_dek_t dek = NULL; byte *data = NULL; u16 chksum = 0; size_t ndata, nbits, nbytes; int i, dlen, pos = 0, nskey; cdk_error_t rc; gcry_error_t err; if (!sk) return CDK_Inv_Value; nskey = cdk_pk_get_nskey (sk->pubkey_algo); if (!sk->is_protected) { chksum = 0; for (i = 0; i < nskey; i++) chksum += checksum_mpi (sk->mpi[i]); if (chksum != sk->csum) return CDK_Chksum_Error; } rc = cdk_dek_from_passphrase (&dek, sk->protect.algo, sk->protect.s2k, 0, pw); if (rc) return rc; err = gcry_cipher_open (&hd, sk->protect.algo, GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_ENABLE_SYNC); if (!err) err = gcry_cipher_setiv (hd, sk->protect.iv, sk->protect.ivlen); if (!err) err = gcry_cipher_setkey (hd, dek->key, dek->keylen); if (err) { cdk_free (dek); return map_gcry_error (err); } cdk_dek_free (dek); chksum = 0; if (sk->version == 4) { ndata = sk->enclen; data = cdk_salloc (ndata, 1); if (!data) return CDK_Out_Of_Core; gcry_cipher_decrypt (hd, data, ndata, sk->encdata, ndata); if (sk->protect.sha1chk) { /* This is the new SHA1 checksum method to detect tampering with the key as used by the Klima/Rosa attack */ sk->csum = 0; chksum = 1; dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1); if (ndata < dlen) { cdk_free (data); return CDK_Inv_Packet; } else { byte mdcheck[20]; gcry_md_hash_buffer (GCRY_MD_SHA1, mdcheck, data, ndata-dlen); if (!memcmp (mdcheck, data + ndata - dlen, dlen)) chksum = 0; /* Digest does match */ } } else { for (i = 0; i < ndata - 2; i++) chksum += data[i]; sk->csum = data[ndata - 2] << 8 | data[ndata - 1]; } if (sk->csum == chksum) { for (i = 0; i < nskey; i++) { nbits = data[pos] << 8 | data[pos + 1]; if (gcry_mpi_scan (&sk->mpi[i], GCRYMPI_FMT_PGP, data, (nbits+7)/8+2, &nbytes)) { wipemem (data, sk->enclen); cdk_free (data); return CDK_Wrong_Format; } gcry_mpi_set_flag (sk->mpi[i], GCRYMPI_FLAG_SECURE); pos += (nbits+7)/8+2; } } wipemem (data, sk->enclen); cdk_free (data); } else { byte buf[MAX_MPI_BYTES+2]; chksum = 0; for (i = 0; i < nskey; i++) { gcry_cipher_sync (hd); gcry_mpi_print (GCRYMPI_FMT_PGP, buf, DIM (buf), &nbytes, sk->mpi[i]); gcry_cipher_decrypt (hd, buf+2, nbytes-2, NULL, 0); gcry_mpi_release (sk->mpi[i]); if (gcry_mpi_scan (&sk->mpi[i], GCRYMPI_FMT_PGP, buf, nbytes, &nbytes)) return CDK_Wrong_Format; chksum += checksum_mpi (sk->mpi[i]); } } gcry_cipher_close (hd); if (chksum != sk->csum) return CDK_Chksum_Error; sk->is_protected = 0; return 0; }