/* Implementation of SHA1-HMAC. We're rolling our own just to * double-check that the calls libotr makes to libgcrypt are in fact * doing the right thing. */ void sha1hmac(unsigned char digest[20], unsigned char key[20], unsigned char *data, size_t datalen) { unsigned char ipad[64], opad[64]; size_t i; gcry_md_hd_t sha1; gcry_error_t err; unsigned char hash[20]; memset(ipad, 0, 64); memset(opad, 0, 64); memmove(ipad, key, 20); memmove(opad, key, 20); for(i=0;i<64;++i) { ipad[i] ^= 0x36; opad[i] ^= 0x5c; } err = gcry_md_open(&sha1, GCRY_MD_SHA1, 0); if (err) { fprintf(stderr, "Error: %s\n", gcry_strerror(err)); exit(1); } gcry_md_write(sha1, ipad, 64); gcry_md_write(sha1, data, datalen); memmove(hash, gcry_md_read(sha1, 0), 20); gcry_md_reset(sha1); gcry_md_write(sha1, opad, 64); gcry_md_write(sha1, hash, 20); memmove(digest, gcry_md_read(sha1, 0), 20); gcry_md_close(sha1); }
static void bench_hash_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { gcry_md_hd_t hd = obj->priv; gcry_md_reset (hd); gcry_md_write (hd, buf, buflen); gcry_md_final (hd); }
extern void io_encryption_checksum_init(IO_HANDLE ptr, enum gcry_md_algos h) { io_private_t *io_ptr = ptr; if (!io_ptr || io_ptr->fd < 0) return errno = EBADF , (void)NULL; io_ptr->hash_init ? gcry_md_reset(io_ptr->hash_handle) : gcry_md_open(&io_ptr->hash_handle, h, GCRY_MD_FLAG_SECURE); io_ptr->hash_init = true; return; }
static int hmac_reset(lua_State *L) { HANDLER_HMAC *c = hmac_pget(L, 1); #if CRYPTO_OPENSSL HMAC_Init_ex(c, NULL, 0, NULL, NULL); #elif CRYPTO_GCRYPT gcry_md_reset(*c); #endif return 0; }
static int evp_reset(lua_State *L) { HANDLER_EVP *c = evp_pget(L, 1); #if CRYPTO_OPENSSL const EVP_MD *t = EVP_MD_CTX_md(c); EVP_MD_CTX_cleanup(c); EVP_MD_CTX_init(c); EVP_DigestInit_ex(c, t, NULL); #elif CRYPTO_GCRYPT gcry_md_reset(*c); #endif return 0; }
int journal_file_hmac_start(JournalFile *f) { uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */ assert(f); if (!f->seal) return 0; if (f->hmac_running) return 0; /* Prepare HMAC for next cycle */ gcry_md_reset(f->hmac); FSPRG_GetKey(f->fsprg_state, key, sizeof(key), 0); gcry_md_setkey(f->hmac, key, sizeof(key)); f->hmac_running = true; return 0; }
void stretch_key(const char *pass, size_t passlen, const uint8_t *salt, uint32_t iter, uint8_t *skey) { gcry_error_t gerr; gcry_md_hd_t sha256; gerr = gcry_md_open(&sha256, GCRY_MD_SHA256, GCRY_MD_FLAG_SECURE); if (gerr != GPG_ERR_NO_ERROR) gcrypt_fatal(gerr); gcry_md_write(sha256, pass, passlen); gcry_md_write(sha256, salt, 32); memmove(skey, gcry_md_read(sha256, 0), 32); while (iter-- > 0) { gcry_md_reset(sha256); gcry_md_write(sha256, skey, 32); memmove(skey, gcry_md_read(sha256, 0), 32); } gcry_md_close(sha256); }
/* calculate the HMAC of the message in data and store it in result * it is up to the caller to make sure that there's enough space * at result for the MAC */ int calc_hmac(const void *data, size_t datalen, int hid, unsigned char *result, char *key, unsigned int keylen) { static gcry_md_hd_t digest; gcry_error_t err; if (!digest) { err = gcry_md_open(&digest, hid, GCRY_MD_FLAG_HMAC); if (err) { log_error("gcry_md_open: %s", gcry_strerror(err)); return -1; } err = gcry_md_setkey(digest, key, keylen); if (err) { log_error("gcry_md_open: %s", gcry_strerror(err)); return -1; } } gcry_md_write(digest, data, datalen); memcpy(result, gcry_md_read(digest, 0), gcry_md_get_algo_dlen(hid)); gcry_md_reset(digest); return 0; }
static void split(gcry_md_hd_t md, FILE *chunk, const char *directory) { const size_t HASH_BYTES = (HASH_BITS + 7) / 8; uint8_t *hashed = gcry_md_read(md, HASH_ALGORITHM); char name[2 * HASH_BYTES + 1]; for (size_t i = 0; i != HASH_BYTES; i++) { const char HEX[] = "0123456789abcdef"; name[2 * i] = HEX[hashed[i] >> 4]; name[2 * i + 1] = HEX[hashed[i] & 15]; } name[2 * HASH_BYTES] = '\0'; if (directory) { char fileName[strlen(directory) + 1 + 2 * HASH_BYTES + 1]; sprintf(fileName, "%s/%s", directory, name); remove(fileName); rename(TMP_FILE_NAME, fileName); } else { remove(name); rename(TMP_FILE_NAME, name); } gcry_md_reset(md); freopen(TMP_FILE_NAME, "wb", chunk); printf("%s\n", name); }
/* Create an OTR Data message. Pass the plaintext as msg, and an * optional chain of TLVs. A newly-allocated string will be returned in * *encmessagep. */ gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context, const char *msg, const OtrlTLV *tlvs, unsigned char flags) { size_t justmsglen = strlen(msg); size_t msglen = justmsglen + 1 + otrl_tlv_seriallen(tlvs); size_t buflen; size_t pubkeylen; unsigned char *buf = NULL; unsigned char *bufp; size_t lenp; DH_sesskeys *sess = &(context->sesskeys[1][0]); gcry_error_t err; size_t reveallen = 20 * context->numsavedkeys; size_t base64len; char *base64buf = NULL; unsigned char *msgbuf = NULL; enum gcry_mpi_format format = GCRYMPI_FMT_USG; char *msgdup; int version = context->protocol_version; /* Make sure we're actually supposed to be able to encrypt */ if (context->msgstate != OTRL_MSGSTATE_ENCRYPTED || context->their_keyid == 0) { return gcry_error(GPG_ERR_CONFLICT); } /* We need to copy the incoming msg, since it might be an alias for * context->lastmessage, which we'll be freeing soon. */ msgdup = gcry_malloc_secure(justmsglen + 1); if (msgdup == NULL) { return gcry_error(GPG_ERR_ENOMEM); } strcpy(msgdup, msg); *encmessagep = NULL; /* Header, send keyid, recv keyid, counter, msg len, msg * len of revealed mac keys, revealed mac keys, MAC */ buflen = 3 + (version == 2 ? 1 : 0) + 4 + 4 + 8 + 4 + msglen + 4 + reveallen + 20; gcry_mpi_print(format, NULL, 0, &pubkeylen, context->our_dh_key.pub); buflen += pubkeylen + 4; buf = malloc(buflen); msgbuf = gcry_malloc_secure(msglen); if (buf == NULL || msgbuf == NULL) { free(buf); gcry_free(msgbuf); gcry_free(msgdup); return gcry_error(GPG_ERR_ENOMEM); } memmove(msgbuf, msgdup, justmsglen); msgbuf[justmsglen] = '\0'; otrl_tlv_serialize(msgbuf + justmsglen + 1, tlvs); bufp = buf; lenp = buflen; if (version == 1) { memmove(bufp, "\x00\x01\x03", 3); /* header */ } else { memmove(bufp, "\x00\x02\x03", 3); /* header */ } debug_data("Header", bufp, 3); bufp += 3; lenp -= 3; if (version == 2) { bufp[0] = flags; bufp += 1; lenp -= 1; } write_int(context->our_keyid-1); /* sender keyid */ debug_int("Sender keyid", bufp-4); write_int(context->their_keyid); /* recipient keyid */ debug_int("Recipient keyid", bufp-4); write_mpi(context->our_dh_key.pub, pubkeylen, "Y"); /* Y */ otrl_dh_incctr(sess->sendctr); memmove(bufp, sess->sendctr, 8); /* Counter (top 8 bytes only) */ debug_data("Counter", bufp, 8); bufp += 8; lenp -= 8; write_int(msglen); /* length of encrypted data */ debug_int("Msg len", bufp-4); err = gcry_cipher_reset(sess->sendenc); if (err) goto err; err = gcry_cipher_setctr(sess->sendenc, sess->sendctr, 16); if (err) goto err; err = gcry_cipher_encrypt(sess->sendenc, bufp, msglen, msgbuf, msglen); if (err) goto err; /* encrypted data */ debug_data("Enc data", bufp, msglen); bufp += msglen; lenp -= msglen; gcry_md_reset(sess->sendmac); gcry_md_write(sess->sendmac, buf, bufp-buf); memmove(bufp, gcry_md_read(sess->sendmac, GCRY_MD_SHA1), 20); debug_data("MAC", bufp, 20); bufp += 20; /* MAC */ lenp -= 20; write_int(reveallen); /* length of revealed MAC keys */ debug_int("Revealed MAC length", bufp-4); if (reveallen > 0) { memmove(bufp, context->saved_mac_keys, reveallen); debug_data("Revealed MAC data", bufp, reveallen); bufp += reveallen; lenp -= reveallen; free(context->saved_mac_keys); context->saved_mac_keys = NULL; context->numsavedkeys = 0; } assert(lenp == 0); /* Make the base64-encoding. */ base64len = ((buflen + 2) / 3) * 4; base64buf = malloc(5 + base64len + 1 + 1); if (base64buf == NULL) { err = gcry_error(GPG_ERR_ENOMEM); goto err; } memmove(base64buf, "?OTR:", 5); otrl_base64_encode(base64buf+5, buf, buflen); base64buf[5 + base64len] = '.'; base64buf[5 + base64len + 1] = '\0'; free(buf); gcry_free(msgbuf); *encmessagep = base64buf; gcry_free(context->lastmessage); context->lastmessage = NULL; context->may_retransmit = 0; if (msglen > 0) { const char *prefix = "[resent] "; size_t prefixlen = strlen(prefix); if (!strncmp(prefix, msgdup, prefixlen)) { /* The prefix is already there. Don't add it again. */ prefix = ""; prefixlen = 0; } context->lastmessage = gcry_malloc_secure(prefixlen + justmsglen + 1); if (context->lastmessage) { strcpy(context->lastmessage, prefix); strcat(context->lastmessage, msgdup); } } gcry_free(msgdup); return gcry_error(GPG_ERR_NO_ERROR); err: free(buf); gcry_free(msgbuf); gcry_free(msgdup); *encmessagep = NULL; return err; }
int close_md(struct md_container* md) { int i; #ifdef _PARAMETER_CHECK_ if (md==NULL) { return RETFAIL; } #endif error(255,"close_md called \n"); #ifdef WITH_MHASH for(i=0;i<=HASH_MHASH_COUNT;i++) { if (md->mhash_mdh[i]!=MHASH_FAILED) { mhash (md->mhash_mdh[i], NULL, 0); } } #endif /* WITH_MHASH */ #ifdef WITH_GCRYPT gcry_md_final(md->mdh); /* Let's flush the buffers */ #define get_libgcrypt_hash(a,b,c,d) \ if(md->calc_attr&a&HASH_USE_GCRYPT){\ error(255,"Getting hash %i\n",b);\ memcpy(md->c,gcry_md_read(md->mdh,b),d);\ } get_libgcrypt_hash(DB_MD5,GCRY_MD_MD5,md5,HASH_MD5_LEN); get_libgcrypt_hash(DB_SHA1,GCRY_MD_SHA1,sha1,HASH_SHA1_LEN); get_libgcrypt_hash(DB_TIGER,GCRY_MD_TIGER,tiger,HASH_TIGER_LEN); get_libgcrypt_hash(DB_RMD160,GCRY_MD_RMD160,rmd160,HASH_RMD160_LEN); get_libgcrypt_hash(DB_SHA256,GCRY_MD_SHA256,sha256,HASH_SHA256_LEN); get_libgcrypt_hash(DB_SHA512,GCRY_MD_SHA512,sha512,HASH_SHA512_LEN); get_libgcrypt_hash(DB_CRC32,GCRY_MD_CRC32,crc32,HASH_CRC32_LEN); /*. There might be more hashes in the library. Add those here.. */ gcry_md_reset(md->mdh); #endif #ifdef WITH_MHASH #define get_mhash_hash(b,c) \ if(md->mhash_mdh[b]!=MHASH_FAILED){ \ mhash_deinit(md->mhash_mdh[b],(void*)md->c); \ } get_mhash_hash(MHASH_MD5,md5); get_mhash_hash(MHASH_SHA1,sha1); get_mhash_hash(MHASH_TIGER,tiger); get_mhash_hash(MHASH_RMD160,rmd160); get_mhash_hash(MHASH_CRC32,crc32); get_mhash_hash(MHASH_HAVAL,haval); get_mhash_hash(MHASH_GOST,gost); get_mhash_hash(MHASH_CRC32B,crc32b); get_mhash_hash(MHASH_SHA256,sha256); get_mhash_hash(MHASH_SHA512,sha512); #ifdef HAVE_MHASH_WHIRLPOOL get_mhash_hash(MHASH_WHIRLPOOL,whirlpool); #endif /* There might be more hashes in the library we want to use. Add those here.. */ #endif return RETOK; }
void clear() { gcry_md_reset( context ); }
gboolean egg_symkey_generate_simple (int cipher_algo, int hash_algo, const gchar *password, gssize n_password, const guchar *salt, gsize n_salt, int iterations, guchar **key, guchar **iv) { gcry_md_hd_t mdh; gcry_error_t gcry; guchar *digest; guchar *digested; guint n_digest; gint pass, i; gint needed_iv, needed_key; guchar *at_iv, *at_key; g_assert (cipher_algo); g_assert (hash_algo); g_return_val_if_fail (iterations >= 1, FALSE); if (!password) n_password = 0; if (n_password == -1) n_password = strlen (password); /* * If cipher algo needs more bytes than hash algo has available * then the entire hashing process is done again (with the previous * hash bytes as extra input), and so on until satisfied. */ needed_key = gcry_cipher_get_algo_keylen (cipher_algo); needed_iv = gcry_cipher_get_algo_blklen (cipher_algo); gcry = gcry_md_open (&mdh, hash_algo, 0); if (gcry) { g_warning ("couldn't create '%s' hash context: %s", gcry_md_algo_name (hash_algo), gcry_strerror (gcry)); return FALSE; } n_digest = gcry_md_get_algo_dlen (hash_algo); g_return_val_if_fail (n_digest > 0, FALSE); digest = egg_secure_alloc (n_digest); g_return_val_if_fail (digest, FALSE); if (key) { *key = egg_secure_alloc (needed_key); g_return_val_if_fail (*key, FALSE); } if (iv) *iv = g_new0 (guchar, needed_iv); at_key = key ? *key : NULL; at_iv = iv ? *iv : NULL; for (pass = 0; TRUE; ++pass) { gcry_md_reset (mdh); /* Hash in the previous buffer on later passes */ if (pass > 0) gcry_md_write (mdh, digest, n_digest); if (password) gcry_md_write (mdh, password, n_password); if (salt && n_salt) gcry_md_write (mdh, salt, n_salt); gcry_md_final (mdh); digested = gcry_md_read (mdh, 0); g_return_val_if_fail (digested, FALSE); memcpy (digest, digested, n_digest); for (i = 1; i < iterations; ++i) { gcry_md_reset (mdh); gcry_md_write (mdh, digest, n_digest); gcry_md_final (mdh); digested = gcry_md_read (mdh, 0); g_return_val_if_fail (digested, FALSE); memcpy (digest, digested, n_digest); } /* Copy as much as possible into the destinations */ i = 0; while (needed_key && i < n_digest) { if (at_key) *(at_key++) = digest[i]; needed_key--; i++; } while (needed_iv && i < n_digest) { if (at_iv) *(at_iv++) = digest[i]; needed_iv--; i++; } if (needed_key == 0 && needed_iv == 0) break; } egg_secure_free (digest); gcry_md_close (mdh); return TRUE; }
/* * Begin hashing */ void ni_hashctx_begin(ni_hashctx_t *ctx) { gcry_md_reset(ctx->handle); }
/* Hash a passphrase using the supplied s2k. Always needs: dek->algo, s2k->mode, s2k->hash_algo. */ static void hash_passphrase ( DEK *dek, char *pw, STRING2KEY *s2k) { gcry_md_hd_t md; int pass, i; int used = 0; int pwlen = strlen(pw); assert ( s2k->hash_algo ); dek->keylen = openpgp_cipher_get_algo_keylen (dek->algo); if ( !(dek->keylen > 0 && dek->keylen <= DIM(dek->key)) ) BUG(); if (gcry_md_open (&md, s2k->hash_algo, 1)) BUG (); for (pass=0; used < dek->keylen ; pass++ ) { if ( pass ) { gcry_md_reset (md); for (i=0; i < pass; i++ ) /* Preset the hash context. */ gcry_md_putc (md, 0 ); } if ( s2k->mode == 1 || s2k->mode == 3 ) { int len2 = pwlen + 8; ulong count = len2; if ( s2k->mode == 3 ) { count = S2K_DECODE_COUNT(s2k->count); if ( count < len2 ) count = len2; } /* Fixme: To avoid DoS attacks by sending an sym-encrypted packet with a very high S2K count, we should either cap the iteration count or CPU seconds based timeout. */ /* A little bit complicated because we need a ulong for count. */ while ( count > len2 ) /* maybe iterated+salted */ { gcry_md_write ( md, s2k->salt, 8 ); gcry_md_write ( md, pw, pwlen ); count -= len2; } if ( count < 8 ) gcry_md_write ( md, s2k->salt, count ); else { gcry_md_write ( md, s2k->salt, 8 ); count -= 8; gcry_md_write ( md, pw, count ); } } else gcry_md_write ( md, pw, pwlen ); gcry_md_final( md ); i = gcry_md_get_algo_dlen ( s2k->hash_algo ); if ( i > dek->keylen - used ) i = dek->keylen - used; memcpy (dek->key+used, gcry_md_read (md, s2k->hash_algo), i); used += i; } gcry_md_close(md); }
static void md_bench ( const char *algoname ) { int algo; gcry_md_hd_t hd; int i, j, repcount; char buf_base[1000+15]; size_t bufsize = 1000; char *buf; char *largebuf_base; char *largebuf; char digest[512/8]; gcry_error_t err = GPG_ERR_NO_ERROR; if (!algoname) { for (i=1; i < 400; i++) if (in_fips_mode && i == GCRY_MD_MD5) ; /* Don't use MD5 in fips mode. */ else if ( !gcry_md_test_algo (i) ) md_bench (gcry_md_algo_name (i)); return; } buf = buf_base + ((16 - ((size_t)buf_base & 0x0f)) % buffer_alignment); algo = gcry_md_map_name (algoname); if (!algo) { fprintf (stderr, PGM ": invalid hash algorithm `%s'\n", algoname); exit (1); } err = gcry_md_open (&hd, algo, 0); if (err) { fprintf (stderr, PGM ": error opening hash algorithm `%s'\n", algoname); exit (1); } for (i=0; i < bufsize; i++) buf[i] = i; printf ("%-12s", gcry_md_algo_name (algo)); start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) for (i=0; i < 1000; i++) gcry_md_write (hd, buf, bufsize); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); gcry_md_reset (hd); start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) for (i=0; i < 10000; i++) gcry_md_write (hd, buf, bufsize/10); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); gcry_md_reset (hd); start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) for (i=0; i < 1000000; i++) gcry_md_write (hd, buf, 1); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) for (i=0; i < 1000; i++) for (j=0; j < bufsize; j++) gcry_md_putc (hd, buf[j]); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); gcry_md_close (hd); /* Now 100 hash operations on 10000 bytes using the fast function. We initialize the buffer so that all memory pages are committed and we have repeatable values. */ if (gcry_md_get_algo_dlen (algo) > sizeof digest) die ("digest buffer too short\n"); largebuf_base = malloc (10000+15); if (!largebuf_base) die ("out of core\n"); largebuf = (largebuf_base + ((16 - ((size_t)largebuf_base & 0x0f)) % buffer_alignment)); for (i=0; i < 10000; i++) largebuf[i] = i; start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) for (i=0; i < 100; i++) gcry_md_hash_buffer (algo, digest, largebuf, 10000); stop_timer (); printf (" %s", elapsed_time ()); free (largebuf_base); putchar ('\n'); fflush (stdout); }
gboolean egg_hkdf_perform (const gchar *hash_algo, gconstpointer input, gsize n_input, gconstpointer salt, gsize n_salt, gconstpointer info, gsize n_info, gpointer output, gsize n_output) { gpointer alloc = NULL; gpointer buffer = NULL; gcry_md_hd_t md1, md2; guint hash_len; gint i; gint flags, algo; gsize step, n_buffer; guchar *at; gcry_error_t gcry; algo = gcry_md_map_name (hash_algo); g_return_val_if_fail (algo != 0, FALSE); hash_len = gcry_md_get_algo_dlen (algo); g_return_val_if_fail (hash_len != 0, FALSE); g_return_val_if_fail (n_output <= 255 * hash_len, FALSE); /* Buffer we need to for intermediate stuff */ if (gcry_is_secure (input)) { flags = GCRY_MD_FLAG_SECURE; buffer = gcry_malloc_secure (hash_len); } else { flags = 0; buffer = gcry_malloc (hash_len); } g_return_val_if_fail (buffer, FALSE); n_buffer = 0; /* Salt defaults to hash_len zeros */ if (!salt) { salt = alloc = g_malloc0 (hash_len); n_salt = hash_len; } /* Step 1: Extract */ gcry = gcry_md_open (&md1, algo, GCRY_MD_FLAG_HMAC | flags); g_return_val_if_fail (gcry == 0, FALSE); gcry = gcry_md_setkey (md1, salt, n_salt); g_return_val_if_fail (gcry == 0, FALSE); gcry_md_write (md1, input, n_input); /* Step 2: Expand */ gcry = gcry_md_open (&md2, algo, GCRY_MD_FLAG_HMAC | flags); g_return_val_if_fail (gcry == 0, FALSE); gcry = gcry_md_setkey (md2, gcry_md_read (md1, algo), hash_len); g_return_val_if_fail (gcry == 0, FALSE); gcry_md_close (md1); at = output; for (i = 1; i < 256; ++i) { gcry_md_reset (md2); gcry_md_write (md2, buffer, n_buffer); gcry_md_write (md2, info, n_info); gcry_md_putc (md2, i); n_buffer = hash_len; memcpy (buffer, gcry_md_read (md2, algo), n_buffer); step = MIN (n_buffer, n_output); memcpy (at, buffer, step); n_output -= step; at += step; if (!n_output) break; } g_free (alloc); gcry_free (buffer); return TRUE; }
/* Accept an OTR Data Message in datamsg. Decrypt it and put the * plaintext into *plaintextp, and any TLVs into tlvsp. Put any * received flags into *flagsp (if non-NULL). */ gcry_error_t otrl_proto_accept_data(char **plaintextp, OtrlTLV **tlvsp, ConnContext *context, const char *datamsg, unsigned char *flagsp) { char *otrtag, *endtag; gcry_error_t err; unsigned char *rawmsg = NULL; size_t msglen, rawlen, lenp; unsigned char *macstart, *macend; unsigned char *bufp; unsigned int sender_keyid, recipient_keyid; gcry_mpi_t sender_next_y = NULL; unsigned char ctr[8]; unsigned int datalen, reveallen; unsigned char *data = NULL; unsigned char *nul = NULL; unsigned char givenmac[20]; DH_sesskeys *sess; unsigned char version; *plaintextp = NULL; *tlvsp = NULL; if (flagsp) *flagsp = 0; otrtag = strstr(datamsg, "?OTR:"); if (!otrtag) { goto invval; } endtag = strchr(otrtag, '.'); if (endtag) { msglen = endtag-otrtag; } else { msglen = strlen(otrtag); } /* Base64-decode the message */ rawlen = ((msglen-5) / 4) * 3; /* maximum possible */ rawmsg = malloc(rawlen); if (!rawmsg && rawlen > 0) { err = gcry_error(GPG_ERR_ENOMEM); goto err; } rawlen = otrl_base64_decode(rawmsg, otrtag+5, msglen-5); /* actual size */ bufp = rawmsg; lenp = rawlen; macstart = bufp; require_len(3); if (memcmp(bufp, "\x00\x01\x03", 3) && memcmp(bufp, "\x00\x02\x03", 3)) { /* Invalid header */ goto invval; } version = bufp[1]; bufp += 3; lenp -= 3; if (version == 2) { require_len(1); if (flagsp) *flagsp = bufp[0]; bufp += 1; lenp -= 1; } read_int(sender_keyid); read_int(recipient_keyid); read_mpi(sender_next_y); require_len(8); memmove(ctr, bufp, 8); bufp += 8; lenp -= 8; read_int(datalen); require_len(datalen); data = malloc(datalen+1); if (!data) { err = gcry_error(GPG_ERR_ENOMEM); goto err; } memmove(data, bufp, datalen); data[datalen] = '\0'; bufp += datalen; lenp -= datalen; macend = bufp; require_len(20); memmove(givenmac, bufp, 20); bufp += 20; lenp -= 20; read_int(reveallen); require_len(reveallen); /* Just skip over the revealed MAC keys, which we don't need. They * were published for deniability of transcripts. */ bufp += reveallen; lenp -= reveallen; /* That should be everything */ if (lenp != 0) goto invval; /* We don't take any action on this message (especially rotating * keys) until we've verified the MAC on this message. To that end, * we need to know which keys this message is claiming to use. */ if (context->their_keyid == 0 || (sender_keyid != context->their_keyid && sender_keyid != context->their_keyid - 1) || (recipient_keyid != context->our_keyid && recipient_keyid != context->our_keyid - 1) || sender_keyid == 0 || recipient_keyid == 0) { goto conflict; } if (sender_keyid == context->their_keyid - 1 && context->their_old_y == NULL) { goto conflict; } /* These are the session keys this message is claiming to use. */ sess = &(context->sesskeys [context->our_keyid - recipient_keyid] [context->their_keyid - sender_keyid]); gcry_md_reset(sess->rcvmac); gcry_md_write(sess->rcvmac, macstart, macend-macstart); if (memcmp(givenmac, gcry_md_read(sess->rcvmac, GCRY_MD_SHA1), 20)) { /* The MACs didn't match! */ goto conflict; } sess->rcvmacused = 1; /* Check to see that the counter is increasing; i.e. that this isn't * a replay. */ if (otrl_dh_cmpctr(ctr, sess->rcvctr) <= 0) { goto conflict; } /* Decrypt the message */ memmove(sess->rcvctr, ctr, 8); err = gcry_cipher_reset(sess->rcvenc); if (err) goto err; err = gcry_cipher_setctr(sess->rcvenc, sess->rcvctr, 16); if (err) goto err; err = gcry_cipher_decrypt(sess->rcvenc, data, datalen, NULL, 0); if (err) goto err; /* See if either set of keys needs rotating */ if (recipient_keyid == context->our_keyid) { /* They're using our most recent key, so generate a new one */ err = rotate_dh_keys(context); if (err) goto err; } if (sender_keyid == context->their_keyid) { /* They've sent us a new public key */ err = rotate_y_keys(context, sender_next_y); if (err) goto err; } gcry_mpi_release(sender_next_y); *plaintextp = (char *)data; /* See if there are TLVs */ nul = data; while (nul < data+datalen && *nul) ++nul; /* If we stopped before the end, skip the NUL we stopped at */ if (nul < data+datalen) ++nul; *tlvsp = otrl_tlv_parse(nul, (data+datalen)-nul); free(rawmsg); return gcry_error(GPG_ERR_NO_ERROR); invval: err = gcry_error(GPG_ERR_INV_VALUE); goto err; conflict: err = gcry_error(GPG_ERR_CONFLICT); goto err; err: gcry_mpi_release(sender_next_y); free(data); free(rawmsg); return err; }
static void crypt_hmac_restart(struct crypt_hmac *ctx) { gcry_md_reset(ctx->hd); }
gcry_error_t gcry_pbkdf2 (int PRF, const char *P, size_t Plen, const char *S, size_t Slen, unsigned int c, unsigned int dkLen, char *DK) { gcry_md_hd_t prf; gcry_error_t rc; char *U; unsigned int u; unsigned int hLen; unsigned int l; unsigned int r; unsigned char *p; unsigned int i; unsigned int k; hLen = gcry_md_get_algo_dlen (PRF); if (hLen == 0) return GPG_ERR_UNSUPPORTED_ALGORITHM; if (c == 0) return GPG_ERR_INV_ARG; if (dkLen == 0) return GPG_ERR_TOO_SHORT; /* * * Steps: * * 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and * stop. */ if (dkLen > 4294967295U) return GPG_ERR_TOO_LARGE; /* * 2. Let l be the number of hLen-octet blocks in the derived key, * rounding up, and let r be the number of octets in the last * block: * * l = CEIL (dkLen / hLen) , * r = dkLen - (l - 1) * hLen . * * Here, CEIL (x) is the "ceiling" function, i.e. the smallest * integer greater than, or equal to, x. */ l = dkLen / hLen; if (dkLen % hLen) l++; r = dkLen - (l - 1) * hLen; /* * 3. For each block of the derived key apply the function F defined * below to the password P, the salt S, the iteration count c, and * the block index to compute the block: * * T_1 = F (P, S, c, 1) , * T_2 = F (P, S, c, 2) , * ... * T_l = F (P, S, c, l) , * * where the function F is defined as the exclusive-or sum of the * first c iterates of the underlying pseudorandom function PRF * applied to the password P and the concatenation of the salt S * and the block index i: * * F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c * * where * * U_1 = PRF (P, S || INT (i)) , * U_2 = PRF (P, U_1) , * ... * U_c = PRF (P, U_{c-1}) . * * Here, INT (i) is a four-octet encoding of the integer i, most * significant octet first. * * 4. Concatenate the blocks and extract the first dkLen octets to * produce a derived key DK: * * DK = T_1 || T_2 || ... || T_l<0..r-1> * * 5. Output the derived key DK. * * Note. The construction of the function F follows a "belt-and- * suspenders" approach. The iterates U_i are computed recursively to * remove a degree of parallelism from an opponent; they are exclusive- * ored together to reduce concerns about the recursion degenerating * into a small set of values. * */ rc = gcry_md_open (&prf, PRF, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE); if (rc != GPG_ERR_NO_ERROR) return rc; U = (char*)gcry_malloc(hLen); if (!U) { rc = GPG_ERR_ENOMEM; goto done; } for (i = 1; i <= l; i++) { memset(DK + (i - 1) * hLen, 0, i == l ? r : hLen); for (u = 1; u <= c; u++) { gcry_md_reset (prf); rc = gcry_md_setkey (prf, P, Plen); if (rc != GPG_ERR_NO_ERROR) { goto done; } if (u == 1) { char tmp[4]; gcry_md_write (prf, S, Slen); tmp[0] = (i & 0xff000000) >> 24; tmp[1] = (i & 0x00ff0000) >> 16; tmp[2] = (i & 0x0000ff00) >> 8; tmp[3] = (i & 0x000000ff) >> 0; gcry_md_write (prf, tmp, 4); } else gcry_md_write (prf, U, hLen); p = gcry_md_read (prf, PRF); if (p == NULL) { rc = GPG_ERR_CONFIGURATION; goto done; } memcpy (U, p, hLen); for (k = 0; k < (i == l ? r : hLen); k++) DK[(i - 1) * hLen + k] ^= U[k]; }
static void md_bench ( const char *algoname ) { int algo; gcry_md_hd_t hd; int i; char buf[1000]; gcry_error_t err = GPG_ERR_NO_ERROR; if (!algoname) { for (i=1; i < 400; i++) if ( !gcry_md_test_algo (i) ) md_bench (gcry_md_algo_name (i)); return; } algo = gcry_md_map_name (algoname); if (!algo) { fprintf (stderr, PGM ": invalid hash algorithm `%s'\n", algoname); exit (1); } err = gcry_md_open (&hd, algo, 0); if (err) { fprintf (stderr, PGM ": error opening hash algorithm `%s'\n", algoname); exit (1); } for (i=0; i < sizeof buf; i++) buf[i] = i; printf ("%-12s", gcry_md_algo_name (algo)); start_timer (); for (i=0; i < 1000; i++) gcry_md_write (hd, buf, sizeof buf); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time ()); gcry_md_reset (hd); start_timer (); for (i=0; i < 10000; i++) gcry_md_write (hd, buf, sizeof buf/10); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time ()); gcry_md_reset (hd); start_timer (); for (i=0; i < 1000000; i++) gcry_md_write (hd, "", 1); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time ()); gcry_md_close (hd); putchar ('\n'); }
static void crypt_hash_restart(struct crypt_hash *ctx) { gcry_md_reset(ctx->hd); }
static int pkcs5_pbkdf2(const char *hash, const char *P, size_t Plen, const char *S, size_t Slen, unsigned int c, unsigned int dkLen, char *DK, int perfcheck) { gcry_md_hd_t prf; char U[MAX_PRF_BLOCK_LEN]; char T[MAX_PRF_BLOCK_LEN]; int PRF, i, k, rc = -EINVAL; unsigned int u, hLen, l, r; unsigned char *p; size_t tmplen = Slen + 4; char *tmp; tmp = alloca(tmplen); if (tmp == NULL) return -ENOMEM; if (init_crypto()) return -ENOSYS; PRF = gcry_md_map_name(hash); if (PRF == 0) return -EINVAL; hLen = gcry_md_get_algo_dlen(PRF); if (hLen == 0 || hLen > MAX_PRF_BLOCK_LEN) return -EINVAL; if (c == 0) return -EINVAL; if (dkLen == 0) return -EINVAL; /* * * Steps: * * 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and * stop. */ if (dkLen > 4294967295U) return -EINVAL; /* * 2. Let l be the number of hLen-octet blocks in the derived key, * rounding up, and let r be the number of octets in the last * block: * * l = CEIL (dkLen / hLen) , * r = dkLen - (l - 1) * hLen . * * Here, CEIL (x) is the "ceiling" function, i.e. the smallest * integer greater than, or equal to, x. */ l = dkLen / hLen; if (dkLen % hLen) l++; r = dkLen - (l - 1) * hLen; /* * 3. For each block of the derived key apply the function F defined * below to the password P, the salt S, the iteration count c, and * the block index to compute the block: * * T_1 = F (P, S, c, 1) , * T_2 = F (P, S, c, 2) , * ... * T_l = F (P, S, c, l) , * * where the function F is defined as the exclusive-or sum of the * first c iterates of the underlying pseudorandom function PRF * applied to the password P and the concatenation of the salt S * and the block index i: * * F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c * * where * * U_1 = PRF (P, S || INT (i)) , * U_2 = PRF (P, U_1) , * ... * U_c = PRF (P, U_{c-1}) . * * Here, INT (i) is a four-octet encoding of the integer i, most * significant octet first. * * 4. Concatenate the blocks and extract the first dkLen octets to * produce a derived key DK: * * DK = T_1 || T_2 || ... || T_l<0..r-1> * * 5. Output the derived key DK. * * Note. The construction of the function F follows a "belt-and- * suspenders" approach. The iterates U_i are computed recursively to * remove a degree of parallelism from an opponent; they are exclusive- * ored together to reduce concerns about the recursion degenerating * into a small set of values. * */ if(gcry_md_open(&prf, PRF, GCRY_MD_FLAG_HMAC)) return -EINVAL; if (gcry_md_setkey(prf, P, Plen)) goto out; for (i = 1; (uint) i <= l; i++) { memset(T, 0, hLen); for (u = 1; u <= c ; u++) { gcry_md_reset(prf); if (u == 1) { memcpy(tmp, S, Slen); tmp[Slen + 0] = (i & 0xff000000) >> 24; tmp[Slen + 1] = (i & 0x00ff0000) >> 16; tmp[Slen + 2] = (i & 0x0000ff00) >> 8; tmp[Slen + 3] = (i & 0x000000ff) >> 0; gcry_md_write(prf, tmp, tmplen); } else { gcry_md_write(prf, U, hLen); } p = gcry_md_read(prf, PRF); if (p == NULL) goto out; memcpy(U, p, hLen); for (k = 0; (uint) k < hLen; k++) T[k] ^= U[k]; if (perfcheck && __PBKDF2_performance) { rc = 0; goto out; } if (perfcheck) __PBKDF2_global_j++; }