extern void io_encryption_checksum(IO_HANDLE ptr, uint8_t **b, size_t *l) { io_private_t *io_ptr = ptr; if (!io_ptr || io_ptr->fd < 0) return errno = EBADF , (void)NULL; if (!io_ptr->hash_init) return *l = 0 , (void)NULL; *l = gcry_md_get_algo_dlen(gcry_md_get_algo(io_ptr->hash_handle)); uint8_t *x = gcry_realloc(*b, *l); if (!x) die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, *l); *b = x; memcpy(*b, gcry_md_read(io_ptr->hash_handle, gcry_md_get_algo(io_ptr->hash_handle)), *l); return; }
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen) { int algo = gcry_md_get_algo(ctx); *mdlen = gcry_md_get_algo_dlen(algo); memcpy(md, gcry_md_read(ctx, algo), *mdlen); gcry_md_close(ctx); }
const char* hash_final( void* d, size_t* hashlen) { gcry_md_hd_t ctx = (gcry_md_hd_t)d; const char* ret = (const char*)gcry_md_read(ctx, 0); // Return the final hash! *hashlen = (size_t)gcry_md_get_algo_dlen(gcry_md_get_algo(ctx)); return ret; }
/**************** * This filter is used to en/de-cipher data with a conventional algorithm */ int cipher_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len) { size_t size = *ret_len; cipher_filter_context_t *cfx = opaque; int rc=0; if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */ rc = -1; /* not yet used */ } else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ assert(a); if( !cfx->header ) { write_header( cfx, a ); } if (cfx->mdc_hash) gcry_md_write (cfx->mdc_hash, buf, size); gcry_cipher_encrypt (cfx->cipher_hd, buf, size, NULL, 0); rc = iobuf_write( a, buf, size ); } else if( control == IOBUFCTRL_FREE ) { if( cfx->mdc_hash ) { byte *hash; int hashlen = gcry_md_get_algo_dlen (gcry_md_get_algo (cfx->mdc_hash)); byte temp[22]; assert( hashlen == 20 ); /* We must hash the prefix of the MDC packet here. */ temp[0] = 0xd3; temp[1] = 0x14; gcry_md_putc (cfx->mdc_hash, temp[0]); gcry_md_putc (cfx->mdc_hash, temp[1]); gcry_md_final (cfx->mdc_hash); hash = gcry_md_read (cfx->mdc_hash, 0); memcpy(temp+2, hash, 20); gcry_cipher_encrypt (cfx->cipher_hd, temp, 22, NULL, 0); gcry_md_close (cfx->mdc_hash); cfx->mdc_hash = NULL; if( iobuf_write( a, temp, 22 ) ) log_error("writing MDC packet failed\n" ); } gcry_cipher_close (cfx->cipher_hd); } else if( control == IOBUFCTRL_DESC ) { *(char**)buf = "cipher_filter"; } return rc; }
static int evp_digest(lua_State *L) { HANDLER_EVP *c = evp_pget(L, 1); #if CRYPTO_OPENSSL HANDLER_EVP *d = NULL; unsigned char digest[EVP_MAX_MD_SIZE]; #elif CRYPTO_GCRYPT HANDLER_EVP d = NULL; unsigned char *digest; int algo; #endif size_t written = 0; if (lua_isstring(L, 2)) { size_t s_len; const char *s = luaL_checklstring(L, 2, &s_len); EVP_UPDATE(c, s, s_len); } #if CRYPTO_OPENSSL d = EVP_MD_CTX_create(); EVP_MD_CTX_copy_ex(d, c); EVP_DigestFinal_ex(d, digest, &written); EVP_MD_CTX_destroy(d); #elif CRYPTO_GCRYPT algo = gcry_md_get_algo(*c); gcry_md_copy(&d, *c); gcry_md_final(d); digest = gcry_md_read(d, algo); written = gcry_md_get_algo_dlen(algo); #endif if (lua_toboolean(L, 3)) lua_pushlstring(L, (char *)digest, written); else { char *hex = bin2hex(digest, written); lua_pushlstring(L, hex, written*2); free(hex); } #if CRYPTO_GCRYPT gcry_md_close(d); #endif return 1; }
static int wrap_gcry_mac_output (void *src_ctx, void *digest, size_t digestsize) { opaque *_digest = gcry_md_read (src_ctx, 0); if (_digest != NULL) { unsigned int len = gcry_md_get_algo_dlen (gcry_md_get_algo (src_ctx)); if (len <= digestsize && digest != NULL) memcpy (digest, _digest, len); return 0; } gnutls_assert (); return GNUTLS_E_HASH_FAILED; }
static int hmac_digest(lua_State *L) { HANDLER_HMAC *c = hmac_pget(L, 1); size_t written = 0; #if CRYPTO_OPENSSL unsigned char digest[EVP_MAX_MD_SIZE]; #elif CRYPTO_GCRYPT HANDLER_HMAC d; unsigned char *digest; int algo; #endif if (lua_isstring(L, 2)) { size_t s_len; const char *s = luaL_checklstring(L, 2, &s_len); HMAC_UPDATE(c, s, s_len); } #if CRYPTO_OPENSSL HMAC_Final(c, digest, &written); #elif CRYPTO_GCRYPT algo = gcry_md_get_algo(*c); gcry_md_copy(&d, *c); gcry_md_final(d); digest = gcry_md_read(d, algo); written = gcry_md_get_algo_dlen(algo); #endif if (lua_toboolean(L, 3)) lua_pushlstring(L, (char *)digest, written); else { char *hex = bin2hex(digest, written); lua_pushlstring(L, hex, written*2); free(hex); } #if CRYPTO_GCRYPT gcry_md_close(d); #endif return 1; }
void hmac_final(HMACCTX c, unsigned char *hashmacbuf, unsigned int *len) { *len = gcry_md_get_algo_dlen(gcry_md_get_algo(c)); memcpy(hashmacbuf, gcry_md_read(c, 0), *len); gcry_md_close(c); }
/* * This filter is used to en/de-cipher data with a symmetric algorithm */ int cipher_filter_cfb (void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len) { cipher_filter_context_t *cfx = opaque; size_t size = *ret_len; int rc = 0; if (control == IOBUFCTRL_UNDERFLOW) /* decrypt */ { rc = -1; /* not yet used */ } else if (control == IOBUFCTRL_FLUSH) /* encrypt */ { log_assert (a); if (!cfx->wrote_header) write_header (cfx, a); if (cfx->mdc_hash) gcry_md_write (cfx->mdc_hash, buf, size); gcry_cipher_encrypt (cfx->cipher_hd, buf, size, NULL, 0); if (cfx->short_blklen_warn) { cfx->short_blklen_count += size; if (cfx->short_blklen_count > (150 * 1024 * 1024)) { log_info ("WARNING: encrypting more than %d MiB with algorithm " "%s should be avoided\n", 150, openpgp_cipher_algo_name (cfx->dek->algo)); cfx->short_blklen_warn = 0; /* Don't show again. */ } } rc = iobuf_write (a, buf, size); } else if (control == IOBUFCTRL_FREE) { if (cfx->mdc_hash) { byte *hash; int hashlen = gcry_md_get_algo_dlen (gcry_md_get_algo(cfx->mdc_hash)); byte temp[22]; log_assert (hashlen == 20); /* We must hash the prefix of the MDC packet here. */ temp[0] = 0xd3; temp[1] = 0x14; gcry_md_putc (cfx->mdc_hash, temp[0]); gcry_md_putc (cfx->mdc_hash, temp[1]); gcry_md_final (cfx->mdc_hash); hash = gcry_md_read (cfx->mdc_hash, 0); memcpy(temp+2, hash, 20); gcry_cipher_encrypt (cfx->cipher_hd, temp, 22, NULL, 0); gcry_md_close (cfx->mdc_hash); cfx->mdc_hash = NULL; if (iobuf_write( a, temp, 22)) log_error ("writing MDC packet failed\n"); } gcry_cipher_close (cfx->cipher_hd); } else if (control == IOBUFCTRL_DESC) { mem2str (buf, "cipher_filter_cfb", *ret_len); } return rc; }
extern void io_encryption_init(IO_HANDLE ptr, enum gcry_cipher_algos c, enum gcry_md_algos h, enum gcry_cipher_modes m, const uint8_t *k, size_t l, io_extra_t x) { io_private_t *io_ptr = ptr; if (!io_ptr || io_ptr->fd < 0) return errno = EBADF , (void)NULL; /* * start setting up the encryption buffer */ if (!(io_ptr->buffer_crypt = gcry_malloc_secure(sizeof( buffer_t )))) die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, sizeof( buffer_t )); gcry_md_open(&io_ptr->hash_handle, h, GCRY_MD_FLAG_SECURE); gcry_cipher_open(&io_ptr->cipher_handle, c, m, GCRY_CIPHER_SECURE); /* * generate a hash of the supplied key data */ size_t hash_length = gcry_md_get_algo_dlen(h); uint8_t *hash = gcry_malloc_secure(hash_length); if (!hash) die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, hash_length); gcry_md_hash_buffer(gcry_md_get_algo(io_ptr->hash_handle), hash, k, l); /* * set the key as the hash of supplied data */ size_t key_length = gcry_cipher_get_algo_keylen(c); uint8_t *key = gcry_calloc_secure(key_length, sizeof( byte_t )); if (!key) die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, key_length); memcpy(key, hash, key_length < hash_length ? key_length : hash_length); gcry_cipher_setkey(io_ptr->cipher_handle, key, key_length); /* here is where it blows-up on Windows 8, using AES */ gcry_free(key); /* * the 2011.* versions (incorrectly) used key length instead of block * length; versions after 2014.06 randomly generate the IV instead */ io_ptr->buffer_crypt->block = gcry_cipher_get_algo_blklen(c); uint8_t *iv = gcry_calloc_secure(x.x_iv == IV_BROKEN ? key_length : io_ptr->buffer_crypt->block, sizeof( byte_t )); if (!iv) die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, io_ptr->buffer_crypt->block); if (x.x_iv == IV_RANDOM) { if (x.x_encrypt) { gcry_create_nonce(iv, io_ptr->buffer_crypt->block); io_write(ptr, iv, io_ptr->buffer_crypt->block); } else io_read(ptr, iv, io_ptr->buffer_crypt->block); } else { uint8_t *iv_hash = gcry_malloc_secure(hash_length); if (!iv_hash) die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, hash_length); /* * set the IV as the hash of the hash */ gcry_md_hash_buffer(gcry_md_get_algo(io_ptr->hash_handle), iv_hash, hash, hash_length); memcpy(iv, iv_hash, io_ptr->buffer_crypt->block < hash_length ? io_ptr->buffer_crypt->block : hash_length); gcry_free(iv_hash); } gcry_free(hash); if (m == GCRY_CIPHER_MODE_CTR) gcry_cipher_setctr(io_ptr->cipher_handle, iv, io_ptr->buffer_crypt->block); else gcry_cipher_setiv(io_ptr->cipher_handle, iv, io_ptr->buffer_crypt->block); gcry_free(iv); /* * set the rest of the buffer */ if (!(io_ptr->buffer_crypt->stream = gcry_malloc_secure(io_ptr->buffer_crypt->block))) die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, io_ptr->buffer_crypt->block); /* * when encrypting/writing data: * 0: length of data buffered so far (in stream) * 1: length of data processed (from d) * when decrypting/reading data: * 0: length of available data in input buffer (stream) * 1: available space in read buffer (d) * 2: next available memory location for data (from d) */ for (unsigned i = 0; i < OFFSET_SLOTS; i++) io_ptr->buffer_crypt->offset[i] = 0; io_ptr->cipher_init = true; io_ptr->hash_init = true; io_ptr->operation = IO_ENCRYPT; return; }
/* Check the signature of an OCSP repsonse. OCSP is the context, S_SIG the signature value and MD the handle of the hash we used for the response. This function automagically finds the correct public key. If SIGNER_FPR_LIST is not NULL, the default OCSP reponder has been used and thus the certificate is one of those identified by the fingerprints. */ static gpg_error_t check_signature (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_sexp_t s_sig, gcry_md_hd_t md, fingerprint_list_t signer_fpr_list) { gpg_error_t err; int algo, cert_idx; gcry_sexp_t s_hash; ksba_cert_t cert; /* Create a suitable S-expression with the hash value of our response. */ gcry_md_final (md); algo = gcry_md_get_algo (md); if (algo != GCRY_MD_SHA1 ) { log_error (_("only SHA-1 is supported for OCSP responses\n")); return gpg_error (GPG_ERR_DIGEST_ALGO); } err = gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash sha1 %b))", gcry_md_get_algo_dlen (algo), gcry_md_read (md, algo)); if (err) { log_error (_("creating S-expression failed: %s\n"), gcry_strerror (err)); return err; } /* Get rid of old OCSP specific certificate references. */ release_ctrl_ocsp_certs (ctrl); if (signer_fpr_list && !signer_fpr_list->next) { /* There is exactly one signer fingerprint given. Thus we use the default OCSP responder's certificate and instantly know the certificate to use. */ cert = get_cert_byhexfpr (signer_fpr_list->hexfpr); if (!cert) cert = get_cert_local (ctrl, signer_fpr_list->hexfpr); if (cert) { err = check_signature_core (ctrl, cert, s_sig, s_hash, signer_fpr_list); ksba_cert_release (cert); cert = NULL; if (!err) { gcry_sexp_release (s_hash); return 0; /* Successfully verified the signature. */ } } } else { char *name; ksba_sexp_t keyid; /* Put all certificates included in the response into the cache and setup a list of those certificate which will later be preferred used when locating certificates. */ for (cert_idx=0; (cert = ksba_ocsp_get_cert (ocsp, cert_idx)); cert_idx++) { cert_ref_t cref; cref = xtrymalloc (sizeof *cref); if (!cref) log_error (_("allocating list item failed: %s\n"), gcry_strerror (err)); else if (!cache_cert_silent (cert, &cref->fpr)) { cref->next = ctrl->ocsp_certs; ctrl->ocsp_certs = cref; } else xfree (cref); } /* Get the certificate by means of the responder ID. */ err = ksba_ocsp_get_responder_id (ocsp, &name, &keyid); if (err) { log_error (_("error getting responder ID: %s\n"), gcry_strerror (err)); return err; } cert = find_cert_bysubject (ctrl, name, keyid); if (!cert) { log_error ("responder certificate "); if (name) log_printf ("'/%s' ", name); if (keyid) { log_printf ("{"); dump_serial (keyid); log_printf ("} "); } log_printf ("not found\n"); } ksba_free (name); ksba_free (keyid); if (cert) { err = check_signature_core (ctrl, cert, s_sig, s_hash, signer_fpr_list); ksba_cert_release (cert); if (!err) { gcry_sexp_release (s_hash); return 0; /* Successfully verified the signature. */ } } } gcry_sexp_release (s_hash); log_error (_("no suitable certificate found to verify the OCSP response\n")); return gpg_error (GPG_ERR_NO_PUBKEY); }