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; }
CK_RV gkm_aes_mechanism_wrap (GkmSession *session, CK_MECHANISM_PTR mech, GkmObject *wrapper, GkmObject *wrapped, CK_BYTE_PTR output, CK_ULONG_PTR n_output) { gcry_cipher_hd_t cih; gcry_error_t gcry; GkmAesKey *key; gpointer value, padded; gsize n_value, n_padded; gsize block, pos; gboolean ret; CK_RV rv; g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR); g_return_val_if_fail (mech, CKR_GENERAL_ERROR); g_return_val_if_fail (mech->mechanism == CKM_AES_CBC_PAD, CKR_GENERAL_ERROR); g_return_val_if_fail (GKM_IS_OBJECT (wrapped), CKR_GENERAL_ERROR); g_return_val_if_fail (n_output, CKR_GENERAL_ERROR); if (!GKM_IS_AES_KEY (wrapper)) return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; key = GKM_AES_KEY (wrapper); block = gkm_aes_key_get_block_size (key); g_return_val_if_fail (block != 0, CKR_GENERAL_ERROR); /* They just want the length */ if (!output) { rv = retrieve_length (session, wrapped, &n_value); if (rv != CKR_OK) return rv; if (!egg_padding_pkcs7_pad (NULL, block, NULL, n_value, NULL, &n_padded)) return CKR_KEY_SIZE_RANGE; *n_output = n_padded; return CKR_OK; } cih = gkm_aes_key_get_cipher (key, GCRY_CIPHER_MODE_CBC); if (cih == NULL) return CKR_FUNCTION_FAILED; if (!mech->pParameter || gcry_cipher_setiv (cih, mech->pParameter, mech->ulParameterLen) != 0) { gcry_cipher_close (cih); return CKR_MECHANISM_PARAM_INVALID; } rv = retrieve_value (session, wrapped, &value, &n_value); if (rv != CKR_OK) { gcry_cipher_close (cih); return rv; } ret = egg_padding_pkcs7_pad (egg_secure_realloc, block, value, n_value, &padded, &n_padded); egg_secure_free (value); if (ret == FALSE) { gcry_cipher_close (cih); return CKR_KEY_SIZE_RANGE; } /* In place encryption */ for (pos = 0; pos < n_padded; pos += block) { gcry = gcry_cipher_encrypt (cih, (guchar*)padded + pos, block, NULL, 0); g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR); } gcry_cipher_close (cih); rv = gkm_util_return_data (output, n_output, padded, n_padded); egg_secure_free (padded); return rv; }