/* Check that forking won't return the same nonce. */ static void check_nonce_forking (void) { pid_t pid; int rp[2]; int i, status; size_t nread; char nonce1[10], nonce1c[10], nonce1p[10]; /* We won't get the same nonce back if we never initialized the nonce subsystem, thus we get one nonce here and forget about it. */ gcry_create_nonce (nonce1, sizeof nonce1); if (verbose) print_hex ("initial nonce: ", nonce1, sizeof nonce1); if (pipe (rp) == -1) die ("pipe failed: %s\n", strerror (errno)); pid = fork (); if (pid == (pid_t)(-1)) die ("fork failed: %s\n", strerror (errno)); if (!pid) { gcry_create_nonce (nonce1c, sizeof nonce1c); if (writen (rp[1], nonce1c, sizeof nonce1c)) die ("write failed: %s\n", strerror (errno)); if (verbose) { print_hex (" child nonce: ", nonce1c, sizeof nonce1c); fflush (stdout); } _exit (0); } gcry_create_nonce (nonce1p, sizeof nonce1p); if (verbose) print_hex (" parent nonce: ", nonce1p, sizeof nonce1p); close (rp[1]); if (readn (rp[0], nonce1c, sizeof nonce1c, &nread)) die ("read failed: %s\n", strerror (errno)); if (nread != sizeof nonce1c) die ("read too short\n"); while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR) ; if (i != (pid_t)(-1) && WIFEXITED (status) && !WEXITSTATUS (status)) ; else die ("child failed\n"); if (!memcmp (nonce1p, nonce1c, sizeof nonce1c)) die ("parent and child got the same nonce\n"); }
/** * @ingroup crypto * Fill block with a random values. * * @param mode desired quality of the random number * @param buffer the buffer to fill * @param length buffer length */ void GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length) { #ifdef gcry_fast_random_poll static unsigned int invokeCount; #endif switch (mode) { case GNUNET_CRYPTO_QUALITY_STRONG: /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */ #ifdef gcry_fast_random_poll if ((invokeCount++ % 256) == 0) gcry_fast_random_poll (); #endif gcry_randomize (buffer, length, GCRY_STRONG_RANDOM); return; case GNUNET_CRYPTO_QUALITY_NONCE: gcry_create_nonce (buffer, length); return; case GNUNET_CRYPTO_QUALITY_WEAK: /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */ #ifdef gcry_fast_random_poll if ((invokeCount++ % 256) == 0) gcry_fast_random_poll (); #endif gcry_randomize (buffer, length, GCRY_WEAK_RANDOM); return; default: GNUNET_assert (0); } }
const gchar* egg_openssl_prep_dekinfo (GHashTable *headers) { gchar *dekinfo, *hex; gsize ivlen; guchar *iv; /* Create the iv */ ivlen = gcry_cipher_get_algo_blklen (GCRY_CIPHER_3DES); g_return_val_if_fail (ivlen, NULL); iv = g_malloc (ivlen); gcry_create_nonce (iv, ivlen); /* And encode it into the string */ hex = egg_hex_encode (iv, ivlen); g_return_val_if_fail (hex, NULL); dekinfo = g_strdup_printf ("DES-EDE3-CBC,%s", hex); g_free (hex); g_free (iv); g_hash_table_insert (headers, g_strdup ("DEK-Info"), (void*)dekinfo); g_hash_table_insert (headers, g_strdup ("Proc-Type"), g_strdup ("4,ENCRYPTED")); return dekinfo; }
char * build_hello (char *sub) { uint8_t *nonce = malloc (32); gcry_create_nonce (nonce, 32); char *bnonce; int nl = base64url_encode_alloc (nonce, 32, &bnonce); time_t current_time; current_time = time(NULL); json_t *obj = json_object(); json_object_set_new(obj, "jti", json_string(bnonce)); json_object_set_new(obj, "sub", json_string(sub)); json_object_set_new(obj, "Version", json_integer(1)); json_object_set_new(obj, "msg_id", json_integer(1)); json_object_set_new(obj, "iat", json_integer (current_time)); json_object_set_new(obj, "exp", json_integer (current_time + 60 * 5)); char * jwt = jwt_encode_old (obj, ES256, hard_sign); assert (NULL != jwt); return jwt; }
void egg_libgcrypt_initialize (void) { static volatile gsize gcrypt_initialized = 0; unsigned seed; if (g_once_init_enter (&gcrypt_initialized)) { /* Only initialize libgcrypt if it hasn't already been initialized */ if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) { #if GCRYPT_VERSION_NUMBER < 0x010600 gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); #endif gcry_check_version (LIBGCRYPT_VERSION); gcry_set_log_handler (log_handler, NULL); gcry_set_outofcore_handler (no_mem_handler, NULL); gcry_set_fatalerror_handler (fatal_handler, NULL); gcry_set_allocation_handler ((gcry_handler_alloc_t)g_malloc, (gcry_handler_alloc_t)egg_secure_alloc, egg_secure_check, (gcry_handler_realloc_t)egg_secure_realloc, egg_secure_free); gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); } gcry_create_nonce (&seed, sizeof (seed)); srand (seed); g_once_init_leave (&gcrypt_initialized, 1); } }
/* Write NBYTES from buffer. If BUFFER is NULL the strong random bytes are written. Returns 0 on success or an error code. */ gsti_error_t _gsti_stream_writen (write_stream_t a, const void *buffer, size_t nbytes) { gsti_error_t err = 0; const unsigned char *s = buffer; if (buffer) { while (nbytes) { if (_gsti_stream_put (a, *s)) { err = a->error; break; } s++; nbytes--; } } else { /* write random padding */ byte * pad = _gsti_xcalloc (1, nbytes); gcry_create_nonce (pad, nbytes); err = _gsti_stream_writen (a, pad, nbytes); gcry_free (pad); } return err; }
static gboolean service_encode_aes_secret (SecretSession *session, SecretValue *value, GVariantBuilder *builder) { gcry_cipher_hd_t cih; guchar *padded; gsize n_padded, pos; gcry_error_t gcry; gpointer iv; gconstpointer secret; gsize n_secret; GVariant *child; g_variant_builder_add (builder, "o", session->path); /* Create the cipher */ gcry = gcry_cipher_open (&cih, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0); if (gcry != 0) { g_warning ("couldn't create AES cipher: %s", gcry_strerror (gcry)); return FALSE; } secret = secret_value_get (value, &n_secret); /* Perform the encoding here */ padded = pkcs7_pad_bytes_in_secure_memory (secret, n_secret, &n_padded); g_assert (padded != NULL); /* Setup the IV */ iv = g_malloc0 (16); gcry_create_nonce (iv, 16); gcry = gcry_cipher_setiv (cih, iv, 16); g_return_val_if_fail (gcry == 0, FALSE); /* Setup the key */ gcry = gcry_cipher_setkey (cih, session->key, session->n_key); g_return_val_if_fail (gcry == 0, FALSE); /* Perform the encryption */ for (pos = 0; pos < n_padded; pos += 16) { gcry = gcry_cipher_encrypt (cih, (guchar*)padded + pos, 16, NULL, 0); g_return_val_if_fail (gcry == 0, FALSE); } gcry_cipher_close (cih); child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), iv, 16, TRUE, g_free, iv); g_variant_builder_add_value (builder, child); child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), padded, n_padded, TRUE, egg_secure_free, padded); g_variant_builder_add_value (builder, child); g_variant_builder_add (builder, "s", secret_value_get_content_type (value)); return TRUE; }
static int wrap_gcry_rnd (void *ctx, int level, void *data, size_t datasize) { if (level == GNUTLS_RND_NONCE) gcry_create_nonce (data, datasize); else gcry_randomize (data, datasize, level); return 0; }
static int wrap_gcry_rnd_init (void **ctx) { char c; gcry_create_nonce (&c, 1); gcry_randomize (&c, 1, GCRY_STRONG_RANDOM); return 0; }
/* When CONFIG_SSL is defined, this implementation replaces the one in * src/util/random.c. */ void random_nonce(unsigned char buf[], size_t size) { #ifdef USE_OPENSSL RAND_pseudo_bytes(buf, size); #elif defined(CONFIG_GNUTLS) gcry_create_nonce(buf, size); #else # error unsupported SSL library #endif }
static void check_nonce (void) { char a[32], b[32]; int i,j; int oops=0; if (verbose) show ("checking gcry_create_nonce\n"); gcry_create_nonce (a, sizeof a); for (i=0; i < 10; i++) { gcry_create_nonce (b, sizeof b); if (!memcmp (a, b, sizeof a)) die ("identical nonce found\n"); } for (i=0; i < 10; i++) { gcry_create_nonce (a, sizeof a); if (!memcmp (a, b, sizeof a)) die ("identical nonce found\n"); } again: for (i=1,j=0; i < sizeof a; i++) if (a[0] == a[i]) j++; if (j+1 == sizeof (a)) { if (oops) die ("impossible nonce found\n"); oops++; gcry_create_nonce (a, sizeof a); goto again; } }
/** * @brief create a random sequence of characters with given length. * @param errorKey holds an error description in case of failure. * @param length the number of random bytes to be generated. * @returns allocated buffer holding a hex-encoded random string or NULL in case of error. Must be freed by the caller. */ char * elektraCryptoGcryCreateRandomString (Key * errorKey, const kdb_unsigned_short_t length) { char * encoded = NULL; kdb_octet_t buffer[length]; gcry_create_nonce (buffer, length); if (CRYPTO_PLUGIN_FUNCTION (base64Encode) (errorKey, buffer, length, &encoded) < 0) { return NULL; } if (!encoded) { ELEKTRA_SET_ERROR (87, errorKey, "Memory allocation failed"); } return encoded; }
/** * Produce a random unsigned 32-bit number modulo @a i. * * @param mode desired quality of the random number * @param i the upper limit (exclusive) for the random number * @return a random value in the interval [0,i[. */ uint32_t GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i) { #ifdef gcry_fast_random_poll static unsigned int invokeCount; #endif uint32_t ret; uint32_t ul; GNUNET_assert (i > 0); switch (mode) { case GNUNET_CRYPTO_QUALITY_STRONG: /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */ #ifdef gcry_fast_random_poll if ((invokeCount++ % 256) == 0) gcry_fast_random_poll (); #endif ul = UINT32_MAX - (UINT32_MAX % i); do { gcry_randomize ((unsigned char *) &ret, sizeof (uint32_t), GCRY_STRONG_RANDOM); } while (ret >= ul); return ret % i; case GNUNET_CRYPTO_QUALITY_NONCE: ul = UINT32_MAX - (UINT32_MAX % i); do { gcry_create_nonce (&ret, sizeof (ret)); } while (ret >= ul); return ret % i; case GNUNET_CRYPTO_QUALITY_WEAK: ret = i * get_weak_random (); if (ret >= i) ret = i - 1; return ret; default: GNUNET_assert (0); } return 0; }
/* The nonce thread. We simply request a couple of nonces and return. */ static THREAD_RET_TYPE nonce_thread (void *argarg) { struct thread_arg_s *arg = argarg; int i; char nonce[NONCE_SIZE]; for (i = 0; i < N_NONCE_ITERATIONS; i++) { gcry_create_nonce (nonce, sizeof nonce); if (i && !(i%100)) show ("thread %d created %d nonces so far", arg->no, i); } gcry_free (arg); return THREAD_RET_VALUE; }
/** * builder: The GTKBuilder * password_type: password type description * * Reads the encrypted data from the prompt and transfers it using output_data. * If crypto is available, it uses crypto. * **/ static void gather_password (GtkBuilder *builder, const gchar *password_type) { GtkEntry *entry; gchar iv[16]; gpointer data; gsize n_data; gchar *name; const gchar *text; gchar *value; name = g_strdup_printf ("%s_entry", password_type); entry = GTK_ENTRY (gtk_builder_get_object (builder, name)); g_return_if_fail (GTK_IS_ENTRY (entry)); g_free (name); if (!gtk_widget_get_realized (GTK_WIDGET (entry))) return; /* A non-encrypted password: just send the value back */ if (!g_key_file_has_group (input_data, "transport")) { text = gtk_entry_get_text (entry); value = egg_hex_encode ((const guchar*)text, strlen (text)); g_key_file_set_string (output_data, password_type, "parameter", ""); g_key_file_set_string (output_data, password_type, "value", value); g_free (value); return; } if (!the_key && !negotiate_transport_crypto ()) { g_warning ("couldn't negotiate transport crypto for password"); return; } gcry_create_nonce (iv, sizeof (iv)); data = gku_prompt_util_encrypt_text (the_key, n_the_key, iv, sizeof (iv), gtk_entry_get_text (entry), &n_data); g_return_if_fail (data); gku_prompt_util_encode_hex (output_data, password_type, "parameter", iv, sizeof (iv)); gku_prompt_util_encode_hex (output_data, password_type, "value", data, n_data); g_free (data); }
static ssize_t enc_write(io_private_t *f, const void *d, size_t l) { size_t remainder[2] = { l, f->buffer_crypt->block - f->buffer_crypt->offset[0] }; /* 0: length of data yet to buffer (from d); 1: available space in output buffer (stream) */ if (!d && !l) { #if defined(__DEBUG__) && !defined(__DEBUG_WITH_ENCRYPTION__) memset(f->buffer_crypt->stream + f->buffer_crypt->offset[0], 0x00, remainder[1]); #else gcry_create_nonce(f->buffer_crypt->stream + f->buffer_crypt->offset[0], remainder[1]); gcry_cipher_encrypt(f->cipher_handle, f->buffer_crypt->stream, f->buffer_crypt->block, NULL, 0); #endif ssize_t e = ecc_write(f, f->buffer_crypt->stream, f->buffer_crypt->block); ecc_sync(f); f->buffer_crypt->block = 0; gcry_free(f->buffer_crypt->stream); f->buffer_crypt->stream = NULL; memset(f->buffer_crypt->offset, 0x00, sizeof f->buffer_crypt->offset); return e; } f->buffer_crypt->offset[1] = 0; while (remainder[0]) { if (remainder[0] < remainder[1]) { memcpy(f->buffer_crypt->stream + f->buffer_crypt->offset[0], d + f->buffer_crypt->offset[1], remainder[0]); f->buffer_crypt->offset[0] += remainder[0]; return l; } memcpy(f->buffer_crypt->stream + f->buffer_crypt->offset[0], d + f->buffer_crypt->offset[1], remainder[1]); #if !defined(__DEBUG__) || defined(__DEBUG_WITH_ENCRYPTION__) gcry_cipher_encrypt(f->cipher_handle, f->buffer_crypt->stream, f->buffer_crypt->block, NULL, 0); #endif ssize_t e = EXIT_SUCCESS; if ((e = ecc_write(f, f->buffer_crypt->stream, f->buffer_crypt->block)) < 0) return e; f->buffer_crypt->offset[0] = 0; memset(f->buffer_crypt->stream, 0x00, f->buffer_crypt->block); f->buffer_crypt->offset[1] += remainder[1]; remainder[0] -= remainder[1]; remainder[1] = f->buffer_crypt->block - f->buffer_crypt->offset[0]; } return l; }
/** * @brief derive the cryptographic key and IV for a given (Elektra) Key k * @param config KeySet holding the plugin/backend configuration * @param errorKey holds an error description in case of failure * @param masterKey holds the decrypted master password from the plugin configuration * @param k the (Elektra)-Key to be encrypted * @param cKey (Elektra)-Key holding the cryptographic material * @param cIv (Elektra)-Key holding the initialization vector * @retval -1 on failure. errorKey holds the error description. * @retval 1 on success */ static int getKeyIvForEncryption (KeySet * config, Key * errorKey, Key * masterKey, Key * k, Key * cKey, Key * cIv) { gcry_error_t gcry_err; kdb_octet_t salt[ELEKTRA_CRYPTO_DEFAULT_SALT_LEN]; kdb_octet_t keyBuffer[KEY_BUFFER_SIZE]; char * saltHexString = NULL; ELEKTRA_ASSERT (masterKey != NULL, "Parameter `masterKey` must not be NULL"); // generate the salt gcry_create_nonce (salt, sizeof (salt)); const int encodingResult = CRYPTO_PLUGIN_FUNCTION (base64Encode) (errorKey, salt, sizeof (salt), &saltHexString); if (encodingResult < 0) { // error in libinvoke - errorKey has been set by base64Encode return -1; } if (!saltHexString) { ELEKTRA_SET_ERROR (87, errorKey, "Memory allocation failed"); return -1; } keySetMeta (k, ELEKTRA_CRYPTO_META_SALT, saltHexString); elektraFree (saltHexString); // read iteration count const kdb_unsigned_long_t iterations = CRYPTO_PLUGIN_FUNCTION (getIterationCount) (errorKey, config); // generate/derive the cryptographic key and the IV if ((gcry_err = gcry_kdf_derive (keyValue (masterKey), keyGetValueSize (masterKey), GCRY_KDF_PBKDF2, GCRY_MD_SHA512, salt, sizeof (salt), iterations, KEY_BUFFER_SIZE, keyBuffer))) { ELEKTRA_SET_ERRORF (ELEKTRA_ERROR_CRYPTO_INTERNAL_ERROR, errorKey, "Failed to create a cryptographic key for encryption because: %s", gcry_strerror (gcry_err)); return -1; } keySetBinary (cKey, keyBuffer, ELEKTRA_CRYPTO_GCRY_KEYSIZE); keySetBinary (cIv, keyBuffer + ELEKTRA_CRYPTO_GCRY_KEYSIZE, ELEKTRA_CRYPTO_GCRY_BLOCKSIZE); return 1; }
gchar * __pkey_manage_aes_encrypt (const gchar *in, const gchar *password) { gchar * result = NULL; gint i; guint in_length = strlen (in); guchar * random_data = NULL; guchar * sha256 = NULL; gchar * sha256_hex = NULL; gchar * cyphered = NULL; random_data = g_new0 (guchar, in_length); // Fill random_data with random data gcry_create_nonce (random_data, in_length); // XOR random_data with in => random_data for (i=0; i<in_length; i++) { random_data[i] = random_data[i] ^ in[i]; } // SHA-2 256 random_data sha256 = g_new0 (guchar, gcry_md_get_algo_dlen(GCRY_MD_SHA256)); gcry_md_hash_buffer (GCRY_MD_SHA256, sha256, random_data, in_length); sha256_hex = __pkey_manage_to_hex (sha256, 32); cyphered = __pkey_manage_aes_encrypt_aux (in, password, &sha256[0], &sha256[16]); result = g_strdup_printf ("gCP%s%s", sha256_hex, cyphered); g_free (sha256_hex); g_free (cyphered); g_free (sha256); g_free (random_data); return result; }
void gcry_mpi_randomize( gcry_mpi_t w, unsigned int nbits, enum gcry_random_level level ) { unsigned char *p; size_t nbytes = (nbits+7)/8; if (level == GCRY_WEAK_RANDOM) { p = mpi_is_secure(w) ? gcry_xmalloc_secure (nbytes) : gcry_xmalloc (nbytes); gcry_create_nonce (p, nbytes); } else { p = mpi_is_secure(w) ? gcry_random_bytes_secure (nbytes, level) : gcry_random_bytes (nbytes, level); } _gcry_mpi_set_buffer( w, p, nbytes, 0 ); gcry_free (p); }
/** * Generate random unsigned 64-bit value. * * @param mode desired quality of the random number * @param max value returned will be in range [0,max) (exclusive) * @return random 64-bit number */ uint64_t GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max) { uint64_t ret; uint64_t ul; GNUNET_assert (max > 0); switch (mode) { case GNUNET_CRYPTO_QUALITY_STRONG: ul = UINT64_MAX - (UINT64_MAX % max); do { gcry_randomize ((unsigned char *) &ret, sizeof (uint64_t), GCRY_STRONG_RANDOM); } while (ret >= ul); return ret % max; case GNUNET_CRYPTO_QUALITY_NONCE: ul = UINT64_MAX - (UINT64_MAX % max); do { gcry_create_nonce (&ret, sizeof (ret)); } while (ret >= ul); return ret % max; case GNUNET_CRYPTO_QUALITY_WEAK: ret = max * get_weak_random (); if (ret >= max) ret = max - 1; return ret; default: GNUNET_assert (0); } return 0; }
cipher::cipher(string k) : encryptor(k) { bool in=false,out=false; in=gcry_cipher_open(&hd_in,GCRY_CIPHER_AES,GCRY_CIPHER_MODE_CBC,0) == 0; out=gcry_cipher_open(&hd_out,GCRY_CIPHER_AES,GCRY_CIPHER_MODE_CBC,0) == 0; if(!in || !out){ goto error_exit; } if( gcry_cipher_setkey(hd_in,&key.front(),16) != 0) { goto error_exit; } if( gcry_cipher_setkey(hd_out,&key.front(),16) != 0) goto error_exit; char iv[16]; gcry_create_nonce(iv,sizeof(iv)); gcry_cipher_setiv(hd_out,iv,sizeof(iv)); return; error_exit: if(in) gcry_cipher_close(hd_in); if(out) gcry_cipher_close(hd_out); throw cppcms_error("AES cipher initialization failed"); }
char * build_hello_rsp (char *sub, json_t *hellorsp) { uint8_t *nonce = malloc (32); gcry_create_nonce (nonce, 32); char *bnonce; int nl = base64url_encode_alloc (nonce, 32, &bnonce); time_t current_time; current_time = time(NULL); json_t *obj = json_object(); double msg_id = json_number_value( json_object_get (hellorsp, "msg_id")); const char *snonce = json_string_value( json_object_get (hellorsp, "jti")); json_object_set_new(obj, "jti", json_string(bnonce)); json_object_set_new(obj, "sub", json_string(sub)); json_object_set_new(obj, "snonce", json_string(snonce)); json_object_set_new(obj, "Version", json_integer(1)); json_object_set_new(obj, "msg_id", json_integer(msg_id + 1)); json_object_set_new(obj, "iat", json_integer (current_time)); json_object_set_new(obj, "exp", json_integer (current_time + 60 * 5)); char * jwt = jwt_encode_old (obj, ES256, hard_sign); assert (NULL != jwt); return jwt; }
/* Initialize the data encryption key (session key). */ static int init_dek (DEK dek) { int rc=0, mode, i; dek->algo = gcry_cipher_map_name (dek->algoid); mode = gcry_cipher_mode_from_oid (dek->algoid); if (!dek->algo || !mode) { log_error ("unsupported algorithm `%s'\n", dek->algoid); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); } /* Extra check for algorithms we consider to be too weak for encryption, although we support them for decryption. Note that there is another check below discriminating on the key length. */ switch (dek->algo) { case GCRY_CIPHER_DES: case GCRY_CIPHER_RFC2268_40: log_error ("cipher algorithm `%s' not allowed: too weak\n", gcry_cipher_algo_name (dek->algo)); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); default: break; } dek->keylen = gcry_cipher_get_algo_keylen (dek->algo); if (!dek->keylen || dek->keylen > sizeof (dek->key)) return gpg_error (GPG_ERR_BUG); dek->ivlen = gcry_cipher_get_algo_blklen (dek->algo); if (!dek->ivlen || dek->ivlen > sizeof (dek->iv)) return gpg_error (GPG_ERR_BUG); /* Make sure we don't use weak keys. */ if (dek->keylen < 100/8) { log_error ("key length of `%s' too small\n", dek->algoid); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); } rc = gcry_cipher_open (&dek->chd, dek->algo, mode, GCRY_CIPHER_SECURE); if (rc) { log_error ("failed to create cipher context: %s\n", gpg_strerror (rc)); return rc; } for (i=0; i < 8; i++) { gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM ); rc = gcry_cipher_setkey (dek->chd, dek->key, dek->keylen); if (gpg_err_code (rc) != GPG_ERR_WEAK_KEY) break; log_info(_("weak key created - retrying\n") ); } if (rc) { log_error ("failed to set the key: %s\n", gpg_strerror (rc)); gcry_cipher_close (dek->chd); dek->chd = NULL; return rc; } gcry_create_nonce (dek->iv, dek->ivlen); rc = gcry_cipher_setiv (dek->chd, dek->iv, dek->ivlen); if (rc) { log_error ("failed to set the IV: %s\n", gpg_strerror (rc)); gcry_cipher_close (dek->chd); dek->chd = NULL; return rc; } return 0; }
gpointer encrypt_file (const gchar *input_file_path, const gchar *pwd, const gchar *algo, const gchar *algo_mode) { Metadata *header_metadata = g_new0 (Metadata, 1); CryptoKeys *encryption_keys = g_new0 (CryptoKeys, 1); set_algo_and_mode (header_metadata, algo, algo_mode); gsize algo_key_len = gcry_cipher_get_algo_keylen (header_metadata->algo); gsize algo_blk_len = gcry_cipher_get_algo_blklen (header_metadata->algo); header_metadata->iv_size = algo_blk_len; // iv must be the same size as the block size gcry_create_nonce (header_metadata->iv, header_metadata->iv_size); gcry_create_nonce (header_metadata->salt, KDF_SALT_SIZE); if (!setup_keys (pwd, algo_key_len, header_metadata, encryption_keys)) { multiple_free (2, (gpointer) &encryption_keys, (gpointer) &header_metadata); return g_strdup ("Couldn't setup the encryption keys, exiting..."); } goffset filesize = get_file_size (input_file_path); GError *err = NULL; GFile *in_file = g_file_new_for_path (input_file_path); GFileInputStream *in_stream = g_file_read (in_file, NULL, &err); if (err != NULL) { multiple_gcry_free (3, (gpointer) &encryption_keys->derived_key, (gpointer) &encryption_keys->crypto_key, (gpointer) &encryption_keys->hmac_key); multiple_free (2, (gpointer) &encryption_keys, (gpointer) &header_metadata); g_object_unref (in_file); return g_strdup (err->message); } gchar *output_file_path = g_strconcat (input_file_path, ".enc", NULL); GFile *out_file = g_file_new_for_path (output_file_path); GFileOutputStream *out_stream = g_file_append_to (out_file, G_FILE_CREATE_REPLACE_DESTINATION, NULL, &err); if (err != NULL) { multiple_gcry_free (3, (gpointer) &encryption_keys->derived_key, (gpointer) &encryption_keys->crypto_key, (gpointer) &encryption_keys->hmac_key); multiple_free (3, (gpointer) &encryption_keys, (gpointer) &header_metadata, (gpointer) &output_file_path); multiple_unref (3, (gpointer) &in_file, (gpointer) &out_file, (gpointer) &in_stream); g_input_stream_close (G_INPUT_STREAM (in_stream), NULL, NULL); return g_strdup (err->message); } gcry_cipher_hd_t hd; gcry_cipher_open (&hd, header_metadata->algo, header_metadata->algo_mode, 0); gcry_cipher_setkey (hd, encryption_keys->crypto_key, algo_key_len); gint64 number_of_blocks; gint number_of_padding_bytes; gchar *ret_msg; if (header_metadata->algo_mode == GCRY_CIPHER_MODE_CBC) { set_number_of_blocks_and_padding_bytes (filesize, algo_blk_len, &number_of_blocks, &number_of_padding_bytes); gcry_cipher_setiv (hd, header_metadata->iv, header_metadata->iv_size); ret_msg = encrypt_using_cbc_mode (header_metadata, &hd, number_of_blocks, number_of_padding_bytes, algo_blk_len, in_stream, out_stream); } else { gcry_cipher_setctr (hd, header_metadata->iv, header_metadata->iv_size); ret_msg = encrypt_using_ctr_mode (header_metadata, &hd, filesize, in_stream, out_stream); } if (ret_msg != NULL) { multiple_gcry_free (3, (gpointer) &encryption_keys->derived_key, (gpointer) &encryption_keys->crypto_key, (gpointer) &encryption_keys->hmac_key); multiple_free (3, (gpointer) &encryption_keys, (gpointer) &header_metadata, (gpointer) &output_file_path); multiple_unref (4, (gpointer) &in_file, (gpointer) &out_file, (gpointer) &in_stream, (gpointer) &out_stream); g_input_stream_close (G_INPUT_STREAM (in_stream), NULL, NULL); g_output_stream_close (G_OUTPUT_STREAM (out_stream), NULL, NULL); return g_strdup (ret_msg); } gcry_cipher_close (hd); guchar *hmac = calculate_hmac (output_file_path, encryption_keys->hmac_key, NULL); gssize written_bytes = g_output_stream_write (G_OUTPUT_STREAM (out_stream), hmac, SHA512_DIGEST_SIZE, NULL, &err); if (written_bytes == -1) { multiple_gcry_free (3, (gpointer) &encryption_keys->derived_key, (gpointer) &encryption_keys->crypto_key, (gpointer) &encryption_keys->hmac_key); multiple_free (4, (gpointer) &encryption_keys, (gpointer) &header_metadata, (gpointer) &output_file_path, (gpointer) &hmac); multiple_unref (4, (gpointer) &in_file, (gpointer) &out_file, (gpointer) &in_stream, (gpointer) &out_stream); g_output_stream_close (G_OUTPUT_STREAM (out_stream), NULL, NULL); return g_strdup (err->message); } g_input_stream_close (G_INPUT_STREAM (in_stream), NULL, NULL); g_output_stream_close (G_OUTPUT_STREAM (out_stream), NULL, NULL); multiple_gcry_free (3, (gpointer) &encryption_keys->derived_key, (gpointer) &encryption_keys->crypto_key, (gpointer) &encryption_keys->hmac_key); multiple_free (4, (gpointer) &output_file_path, (gpointer) &encryption_keys, (gpointer) &header_metadata, (gpointer) &hmac); multiple_unref (4, (gpointer) &in_file, (gpointer) &out_file, (gpointer) &in_stream, (gpointer) &out_stream); return NULL; }
netmd_error netmd_prepare_packets(unsigned char* data, size_t data_lenght, netmd_track_packets **packets, size_t *packet_count, unsigned char *key_encryption_key) { size_t position = 0; size_t chunksize = 0xffffffffU; netmd_track_packets *last = NULL; netmd_track_packets *next = NULL; gcry_cipher_hd_t key_handle; gcry_cipher_hd_t data_handle; unsigned char iv[8] = { 0 }; unsigned char rand[8] = { 0 }; netmd_error error = NETMD_NO_ERROR; gcry_cipher_open(&key_handle, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); gcry_cipher_open(&data_handle, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_setkey(key_handle, key_encryption_key, 8); /* generate initial iv */ gcry_create_nonce(iv, sizeof(iv)); *packet_count = 0; while (position < data_lenght) { if ((data_lenght - position) < chunksize) { /* limit chunksize for last packet */ chunksize = data_lenght - position; } if ((chunksize % 8) != 0) { chunksize = chunksize + 8 - (chunksize % 8); } /* alloc memory */ next = malloc(sizeof(netmd_track_packets)); next->length = chunksize; next->data = malloc(next->length); memset(next->data, 0, next->length); next->iv = malloc(8); next->key = malloc(8); next->next = NULL; /* linked list */ if (last != NULL) { last->next = next; } else { *packets = next; } /* generate key */ gcry_randomize(rand, sizeof(rand), GCRY_STRONG_RANDOM); gcry_cipher_decrypt(key_handle, next->key, 8, rand, sizeof(rand)); /* crypt data */ memcpy(next->iv, iv, 8); gcry_cipher_setiv(data_handle, iv, 8); gcry_cipher_setkey(data_handle, rand, sizeof(rand)); gcry_cipher_encrypt(data_handle, next->data, chunksize, data + position, chunksize); memcpy(iv, data + position - 8, 8); /* next packet */ position = position + chunksize; (*packet_count)++; last = next; } gcry_cipher_close(key_handle); gcry_cipher_close(data_handle); return error; }
static gboolean gcr_secret_exchange_default_encrypt_transport_data (GcrSecretExchange *exchange, GckAllocator allocator, const guchar *plain_text, gsize n_plain_text, guchar **iv, gsize *n_iv, guchar **cipher_text, gsize *n_cipher_text) { GcrSecretExchangeDefault *data = exchange->pv->default_exchange; gcry_cipher_hd_t cih; gcry_error_t gcry; guchar *padded; gsize n_result; guchar *result; gsize pos; g_return_val_if_fail (data != NULL, FALSE); g_return_val_if_fail (data->key != NULL, FALSE); gcry = gcry_cipher_open (&cih, EXCHANGE_1_CIPHER_ALGO, EXCHANGE_1_CIPHER_MODE, 0); if (gcry != 0) { g_warning ("couldn't create aes cipher context: %s", gcry_strerror (gcry)); g_free (iv); return FALSE; } *iv = (allocator) (NULL, EXCHANGE_1_IV_LENGTH); g_return_val_if_fail (*iv != NULL, FALSE); gcry_create_nonce (*iv, EXCHANGE_1_IV_LENGTH); *n_iv = EXCHANGE_1_IV_LENGTH; /* 16 = 128 bits */ gcry = gcry_cipher_setkey (cih, data->key, EXCHANGE_1_KEY_LENGTH); g_return_val_if_fail (gcry == 0, FALSE); /* 16 = 128 bits */ gcry = gcry_cipher_setiv (cih, *iv, EXCHANGE_1_IV_LENGTH); g_return_val_if_fail (gcry == 0, FALSE); /* Pad the text properly */ if (!egg_padding_pkcs7_pad (egg_secure_realloc, 16, plain_text, n_plain_text, (gpointer*)&padded, &n_result)) g_return_val_if_reached (FALSE); result = (allocator) (NULL, n_result); g_return_val_if_fail (result != NULL, FALSE); for (pos = 0; pos < n_result; pos += 16) { gcry = gcry_cipher_encrypt (cih, result + pos, 16, padded + pos, 16); g_return_val_if_fail (gcry == 0, FALSE); } gcry_cipher_close (cih); egg_secure_clear (padded, n_result); egg_secure_free (padded); *cipher_text = result; *n_cipher_text = n_result; return TRUE; }
Gc_rc gc_nonce (char *data, size_t datalen) { gcry_create_nonce ((unsigned char *) data, datalen); return GC_OK; }
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; }
void * handle_client(void * arg) { struct thread_data_t * datum = (struct thread_data_t *)(arg); /* Fetch the ID from the argument */ #ifndef NDEBUG fprintf(stderr, "[thread %lu] INFO: worker started\n", datum->id); #endif /* Worker thread signal handling is unique */ sigaction(SIGUSR1, datum->signal_action, NULL); sigaction(SIGUSR2, datum->signal_action, NULL); /* As long as possible, grab up whatever connection is available */ while (!session_data.caught_signal && !datum->caught_signal) { /* Ensure only one worker accepts the next client */ gcry_pthread_mutex_lock((void **)(&session_data.accept_mutex)); datum->sock = accept(session_data.sock, (struct sockaddr *)(&datum->remote_addr), &datum->remote_addr_len); gcry_pthread_mutex_unlock((void **)(&session_data.accept_mutex)); if (datum->sock >= 0) { #ifndef NDEBUG fprintf(stderr, "[thread %lu] INFO: worker connected to client\n", datum->id); #endif /* Receive a "hello" message from the client */ recv_message(&datum->buffet, datum->sock); /* Decrypt it with the default key */ decrypt_message(&datum->buffet, keystore.key); /* Verify it is an authentication request */ if (strncmp(datum->buffet.tbuffer, AUTH_CHECK_MSG, sizeof(AUTH_CHECK_MSG))) { /* Respond with nonce (misdirection) */ gcry_create_nonce(datum->buffet.pbuffer, MAX_COMMAND_LENGTH); encrypt_message(&datum->buffet, keystore.key); send_message(&datum->buffet, datum->sock); } else { /* Request a session key */ gcry_pthread_mutex_lock((void **)(&session_data.keystore_mutex)); #ifndef NDEBUG print_keystore(stderr, "before request"); #endif request_key(&datum->credentials.key); #ifndef NDEBUG print_keystore(stderr, "after request"); #endif gcry_pthread_mutex_unlock((void **)(&session_data.keystore_mutex)); /* Encrypted it using the default key */ salt_and_pepper((char *)(datum->credentials.key), NULL, &datum->buffet); encrypt_message(&datum->buffet, keystore.key); send_message(&datum->buffet, datum->sock); clear_buffet(&datum->buffet); /* Repeatedly poll for message streams */ while (handle_stream(datum) == BANKING_SUCCESS); /* Revoke the session key */ gcry_pthread_mutex_lock((void **)(&session_data.keystore_mutex)); #ifndef NDEBUG print_keystore(stderr, "before revoke"); #endif revoke_key(&datum->credentials.key); #ifndef NDEBUG print_keystore(stderr, "after revoke"); #endif gcry_pthread_mutex_unlock((void **)(&session_data.keystore_mutex)); } /* Cleanup (disconnect) */ #ifndef NDEBUG fprintf(stderr, "[thread %lu] INFO: worker disconnected from client\n", datum->id); #endif clear_buffet(&datum->buffet); destroy_socket(datum->sock); datum->sock = BANKING_FAILURE; } else { fprintf(stderr, "[thread %lu] ERROR: worker unable to connect\n", datum->id); } } /* Teardown */ handle_interruption(0); return NULL; }
/*! \brief Handle a message stream from a client */ int handle_stream(struct thread_data_t * datum) { int i; handle_t hdl; char msg[MAX_COMMAND_LENGTH], * args; /* The initial message is always an authentication request */ recv_message(&datum->buffet, datum->sock); decrypt_message(&datum->buffet, datum->credentials.key); if (strncmp(datum->buffet.tbuffer, AUTH_CHECK_MSG, sizeof(AUTH_CHECK_MSG))) { #ifndef NDEBUG fprintf(stderr, "[thread %lu] INFO: malformed authentication message\n", datum->id); #endif /* Respond with a "mumble" (nonce) */ gcry_create_nonce(datum->buffet.pbuffer, MAX_COMMAND_LENGTH); encrypt_message(&datum->buffet, datum->credentials.key); send_message(&datum->buffet, datum->sock); return BANKING_FAILURE; } /* Turn around the buffer and toss it back */ for (i = 0; i < MAX_COMMAND_LENGTH; ++i) { datum->buffet.pbuffer[i] = datum->buffet.tbuffer[MAX_COMMAND_LENGTH - 1 - i]; } encrypt_message(&datum->buffet, datum->credentials.key); send_message(&datum->buffet, datum->sock); clear_buffet(&datum->buffet); #ifndef NDEBUG fprintf(stderr, "[thread %lu] INFO: authentication successful\n", datum->id); #endif /* Read the actual command */ recv_message(&datum->buffet, datum->sock); decrypt_message(&datum->buffet, datum->credentials.key); /* Copy the command into a buffer so more can be received */ strncpy(msg, datum->buffet.tbuffer, MAX_COMMAND_LENGTH); #ifndef NDEBUG /* Local echo for all received messages */ fprintf(stderr, "[thread %lu] INFO: worker received message:\n", datum->id); hexdump(stderr, (unsigned char *)(msg), MAX_COMMAND_LENGTH); #endif /* Disconnect from any client that issues malformed commands */ if (fetch_handle(msg, &hdl, &args)) { /* Respond with a "mumble" (nonce) */ gcry_create_nonce(datum->buffet.pbuffer, MAX_COMMAND_LENGTH); encrypt_message(&datum->buffet, datum->credentials.key); send_message(&datum->buffet, datum->sock); clear_buffet(&datum->buffet); return BANKING_FAILURE; } /* We are signaled by failed handlers */ datum->caught_signal = hdl(datum, args); clear_buffet(&datum->buffet); return BANKING_SUCCESS; }