void cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) { const Cipher *c = cc->cipher; int evplen; switch (c->number) { case SSH_CIPHER_SSH2: case SSH_CIPHER_DES: case SSH_CIPHER_BLOWFISH: evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); if (evplen <= 0) return; if ((u_int)evplen != len) fatal("%s: wrong iv length %d != %d", __func__, evplen, len); if (cipher_authlen(c)) { if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, len, iv)) fatal("%s: EVP_CTRL_GCM_IV_GEN", __func__); } else memcpy(iv, cc->evp.iv, len); break; case SSH_CIPHER_3DES: ssh1_3des_iv(&cc->evp, 0, iv, 24); break; default: fatal("%s: bad cipher %d", __func__, c->number); } }
int cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv, size_t len) { #ifdef WITH_OPENSSL const struct sshcipher *c = cc->cipher; int evplen = 0; #endif if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) return 0; if ((cc->cipher->flags & CFLAG_NONE) != 0) return 0; #ifdef WITH_OPENSSL evplen = EVP_CIPHER_CTX_iv_length(cc->evp); if (evplen <= 0) return SSH_ERR_LIBCRYPTO_ERROR; if ((size_t)evplen != len) return SSH_ERR_INVALID_ARGUMENT; #ifndef OPENSSL_HAVE_EVPCTR /* XXX iv arg is const, but ssh_aes_ctr_iv isn't */ if (c->evptype == evp_aes_128_ctr) ssh_aes_ctr_iv(cc->evp, 1, (u_char *)iv, evplen); else #endif if (cipher_authlen(c)) { /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */ if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv)) return SSH_ERR_LIBCRYPTO_ERROR; } else if (!EVP_CIPHER_CTX_set_iv(cc->evp, iv, evplen)) return SSH_ERR_LIBCRYPTO_ERROR; #endif return 0; }
void cipher_set_keyiv(CipherContext *cc, u_char *iv) { const Cipher *c = cc->cipher; int evplen = 0; switch (c->number) { case SSH_CIPHER_SSH2: case SSH_CIPHER_DES: case SSH_CIPHER_BLOWFISH: evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); if (evplen == 0) return; if (cipher_authlen(c)) { if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, -1, iv)) fatal("%s: EVP_CTRL_GCM_SET_IV_FIXED failed", __func__); } else memcpy(cc->evp.iv, iv, evplen); break; case SSH_CIPHER_3DES: ssh1_3des_iv(&cc->evp, 1, iv, 24); break; default: fatal("%s: bad cipher %d", __func__, c->number); } }
JNIEXPORT int JNICALL Java_com_facebook_crypto_cipher_NativeGCMCipher_nativeEncryptFinal( JNIEnv* env, jobject obj, jbyteArray macTag, jint tagLen) { int bytesWritten = 0; EVP_CIPHER_CTX* ctx = Get_Cipher_CTX(env, obj); if (!ctx) { return CRYPTO_FAILURE; } jbyte* tagBytes = (*env)->GetByteArrayElements(env, macTag, NULL); if (!tagBytes) { return CRYPTO_FAILURE; } int retCode = CRYPTO_SUCCESS; if (!retCode || !EVP_EncryptFinal_ex(ctx, tagBytes, &bytesWritten)) { retCode = CRYPTO_FAILURE; } if (!retCode || !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tagLen, tagBytes)) { retCode = CRYPTO_FAILURE; } (*env)->ReleaseByteArrayElements(env, macTag, tagBytes, 0); return retCode; }
/* * aes_gcm_openssl_set_iv(c, iv) sets the counter value to the exor of iv with * the offset */ static srtp_err_status_t srtp_aes_gcm_openssl_set_iv( void *cv, uint8_t *iv, srtp_cipher_direction_t direction) { srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv; if (direction != srtp_direction_encrypt && direction != srtp_direction_decrypt) { return (srtp_err_status_bad_param); } c->dir = direction; debug_print(srtp_mod_aes_gcm, "setting iv: %s", v128_hex_string((v128_t *)iv)); if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0)) { return (srtp_err_status_init_fail); } if (!EVP_CipherInit_ex(c->ctx, NULL, NULL, NULL, iv, (c->dir == srtp_direction_encrypt ? 1 : 0))) { return (srtp_err_status_init_fail); } return (srtp_err_status_ok); }
void cmd_start_crypt_in(struct ctrl_command *cmd) { #ifdef HAVE_LIBCRYPTO if (in_state.crypt) send_error("can't start decryption - already started!"); if (!in_state.crypt_state.cipher) send_error("can't start decryption - no cipher set!"); if (!in_state.crypt_state.key) send_error("can't start decryption - no key set!"); in_state.crypt = 1; if (!EVP_DecryptInit(&in_state.crypt_state.ctx, in_state.crypt_state.cipher, NULL, NULL)) send_error("can't start decryption - DecryptInit (1) failed: %s!", ERR_error_string(ERR_get_error(), NULL)); /* * XXX - ugly hack to work around OpenSSL bug * if/when OpenSSL fix it, or give proper workaround * use that, and force minimum OpenSSL version * * Without this hack, BF/256 will fail. */ /* cast to avoid warning */ *(unsigned int *)( &in_state.crypt_state.ctx.cipher->flags) |= EVP_CIPH_VARIABLE_LENGTH; if (!EVP_CIPHER_CTX_set_key_length(&in_state.crypt_state.ctx, in_state.crypt_state.keylen)) send_error("can't start decryption - set_key_length failed: %s!", ERR_error_string(ERR_get_error(), NULL)); in_state.crypt_state.ivlen = EVP_CIPHER_CTX_iv_length(&in_state.crypt_state.ctx); if (in_state.crypt_state.ivlen) in_state.crypt_state.iv = calloc(in_state.crypt_state.ivlen, 1); if (in_state.crypt_state.rounds) { if (!EVP_CIPHER_CTX_ctrl(&in_state.crypt_state.ctx, EVP_CTRL_SET_RC5_ROUNDS, in_state.crypt_state.rounds, NULL)) send_error("can't start decryption - SET_RC5_ROUNDS failed: %s!", ERR_error_string(ERR_get_error(), NULL)); } if (!EVP_DecryptInit(&in_state.crypt_state.ctx, NULL, in_state.crypt_state.key, in_state.crypt_state.iv)) send_error("can't start decryption - DecryptInit (2) failed: %s!", ERR_error_string(ERR_get_error(), NULL)); #else send_error("can't start decryption - no OpenSSL support!"); #endif }
static int s2n_composite_cipher_aes_sha_initial_hmac(struct s2n_session_key *key, uint8_t *sequence_number, uint8_t content_type, uint16_t protocol_version, uint16_t payload_and_eiv_len, int *extra) { uint8_t ctrl_buf[S2N_TLS12_AAD_LEN]; struct s2n_blob ctrl_blob = { .data = ctrl_buf, .size = S2N_TLS12_AAD_LEN }; struct s2n_stuffer ctrl_stuffer; GUARD(s2n_stuffer_init(&ctrl_stuffer, &ctrl_blob)); GUARD(s2n_stuffer_write_bytes(&ctrl_stuffer, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN)); GUARD(s2n_stuffer_write_uint8(&ctrl_stuffer, content_type)); GUARD(s2n_stuffer_write_uint8(&ctrl_stuffer, protocol_version / 10)); GUARD(s2n_stuffer_write_uint8(&ctrl_stuffer, protocol_version % 10)); GUARD(s2n_stuffer_write_uint16(&ctrl_stuffer, payload_and_eiv_len)); /* This will unnecessarily mangle the input buffer, which is fine since it's temporary * Return value will be length of digest, padding, and padding length byte. * See https://github.com/openssl/openssl/blob/master/crypto/evp/e_aes_cbc_hmac_sha1.c#L814 * and https://github.com/openssl/openssl/blob/4f0c475719defd7c051964ef9964cc6e5b3a63bf/ssl/record/ssl3_record.c#L743 */ int ctrl_ret = EVP_CIPHER_CTX_ctrl(key->evp_cipher_ctx, EVP_CTRL_AEAD_TLS1_AAD, S2N_TLS12_AAD_LEN, ctrl_buf); if (ctrl_ret < 0) { S2N_ERROR(S2N_ERR_INITIAL_HMAC); } *extra = ctrl_ret; return 0; }
sgx_status_t sgx_aes_gcm128_enc_get_mac(uint8_t *mac, sgx_aes_state_handle_t aes_gcm_state) { if ((mac == NULL) || (aes_gcm_state == NULL)) { return SGX_ERROR_INVALID_PARAMETER; } sgx_status_t ret = SGX_ERROR_UNEXPECTED; int tmp = 0; EVP_CIPHER_CTX *pState = (EVP_CIPHER_CTX*)aes_gcm_state; do { // Finalise the encryption // if (1 != EVP_EncryptFinal_ex(pState, NULL, &tmp)) { break; } // Get tag (MAC) // if (!EVP_CIPHER_CTX_ctrl(pState, EVP_CTRL_AEAD_GET_TAG, SGX_AESGCM_MAC_SIZE, mac)) { break; } ret = SGX_SUCCESS; } while (1); //In case of error, clear output MAC buffer. // if (ret != SGX_SUCCESS) { memset_s(mac, SGX_AESGCM_MAC_SIZE, 0, SGX_AESGCM_MAC_SIZE); } return ret; }
Encrypt::Encrypt(CryptoConfig config, Slice key, Slice iv, Slice entity): WithState(State::INITIAL), config_(config), buffer_(VERSION_SIZE + config.ivLength + config.keyLength), version_(buffer_(0, VERSION_SIZE)), iv_(buffer_(VERSION_SIZE, VERSION_SIZE + config.ivLength)), key_(buffer_(VERSION_SIZE + config.ivLength, VERSION_SIZE + config.ivLength + config.keyLength)), entity_(entity.length()), tag_(config_.tagLength) { checkArgument(key.length() == config_.keyLength, "Invalid key"); checkArgument(iv.length() == config_.ivLength, "Invalid IV"); version_[FORMAT_BYTE] = FORMAT_VALUE; version_[CONFIG_BYTE] = config_.id; // copy the data to memory I own iv.copyTo(iv_); key.copyTo(key_); entity.copyTo(entity_); const EVP_CIPHER* cipher = config_.cipher; ctx_ = EVP_CIPHER_CTX_new(); check(ctx_, "Encryption context creation failed"); int code = EVP_EncryptInit_ex(ctx_, cipher, NULL, NULL, NULL); check(code == EVP_SUCCESS, "Encryption context creation failed (cipher)"); code = EVP_CIPHER_CTX_ctrl(ctx_, EVP_CTRL_GCM_SET_IVLEN, config_.ivLength, NULL); check(code == EVP_SUCCESS, "Encryption context creation failed (IV length)"); code = EVP_EncryptInit_ex(ctx_, NULL, NULL, key_.offset(0), iv_.offset(0)); check(code == EVP_SUCCESS, "Encryption initialization failed"); }
/* * This function processes the AAD * * Parameters: * c Crypto context * aad Additional data to process for AEAD cipher suites * aad_len length of aad buffer */ static srtp_err_status_t srtp_aes_gcm_openssl_set_aad(void *cv, const uint8_t *aad, uint32_t aad_len) { srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv; int rv; /* * Set dummy tag, OpenSSL requires the Tag to be set before * processing AAD */ /* * OpenSSL never write to address pointed by the last parameter of * EVP_CIPHER_CTX_ctrl while EVP_CTRL_GCM_SET_TAG (in reality, * OpenSSL copy its content to the context), so we can make * aad read-only in this function and all its wrappers. */ unsigned char dummy_tag[GCM_AUTH_TAG_LEN]; memset(dummy_tag, 0x0, GCM_AUTH_TAG_LEN); EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_TAG, c->tag_len, &dummy_tag); rv = EVP_Cipher(c->ctx, NULL, aad, aad_len); if (rv != aad_len) { return (srtp_err_status_algo_fail); } else { return (srtp_err_status_ok); } }
/* * This function decrypts a buffer using AES GCM mode * * Parameters: * c Crypto context * buf data to encrypt * enc_len length of encrypt buffer */ static srtp_err_status_t srtp_aes_gcm_openssl_decrypt(void *cv, unsigned char *buf, unsigned int *enc_len) { srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv; if (c->dir != srtp_direction_encrypt && c->dir != srtp_direction_decrypt) { return (srtp_err_status_bad_param); } /* * Set the tag before decrypting */ EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_TAG, c->tag_len, buf + (*enc_len - c->tag_len)); EVP_Cipher(c->ctx, buf, buf, *enc_len - c->tag_len); /* * Check the tag */ if (EVP_Cipher(c->ctx, NULL, NULL, 0)) { return (srtp_err_status_auth_fail); } /* * Reduce the buffer size by the tag length since the tag * is not part of the original payload */ *enc_len -= c->tag_len; return (srtp_err_status_ok); }
// ---------------------------------------------------------------------------- bool Crypto::decryptConnectionRequest(BareNetworkString& ns) { std::vector<uint8_t> pt(ns.m_buffer.size() - 4, 0); if (EVP_DecryptInit_ex(m_decrypt, NULL, NULL, NULL, NULL) != 1) return false; int dlen; if (!EVP_CIPHER_CTX_ctrl(m_decrypt, EVP_CTRL_GCM_SET_TAG, 4, ns.m_buffer.data())) return false; if (EVP_DecryptUpdate(m_decrypt, pt.data(), &dlen, ns.m_buffer.data() + 4, (int)(ns.m_buffer.size() - 4)) != 1) return false; if (EVP_DecryptFinal_ex(m_decrypt, unused_16_blocks.data(), &dlen) > 0) { assert(dlen == 0); std::swap(ns.m_buffer, pt); return true; } return false; } // decryptConnectionRequest
int cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv) { #ifdef WITH_OPENSSL const struct sshcipher *c = cc->cipher; int evplen = 0; #endif if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) return 0; if ((cc->cipher->flags & CFLAG_NONE) != 0) return 0; #ifdef WITH_OPENSSL evplen = EVP_CIPHER_CTX_iv_length(cc->evp); if (evplen <= 0) return SSH_ERR_LIBCRYPTO_ERROR; if (cipher_authlen(c)) { /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */ if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, -1, __UNCONST(iv))) return SSH_ERR_LIBCRYPTO_ERROR; } else memcpy(EVP_CIPHER_CTX_iv_noconst(cc->evp), iv, evplen); #endif return 0; }
static int rc2_get_asn1_type_and_iv (EVP_CIPHER_CTX * c, ASN1_TYPE * type) { long num = 0; int i = 0; int key_bits; unsigned int l; unsigned char iv[EVP_MAX_IV_LENGTH]; if (type != NULL) { l = EVP_CIPHER_CTX_iv_length (c); OPENSSL_assert (l <= sizeof (iv)); i = ASN1_TYPE_get_int_octetstring (type, &num, iv, l); if (i != (int) l) return (-1); key_bits = rc2_magic_to_meth ((int) num); if (!key_bits) return (-1); if (i > 0 && !EVP_CipherInit_ex (c, NULL, NULL, NULL, iv, -1)) return -1; EVP_CIPHER_CTX_ctrl (c, EVP_CTRL_SET_RC2_KEY_BITS, key_bits, NULL); EVP_CIPHER_CTX_set_key_length (c, key_bits / 8); } return (i); }
static int decrypt_data(char *in, int len, char *out) { unsigned char outbuf[MAX_LEN]; unsigned char iv[IV_SIZE]; unsigned char tag[16]; char *step; int tmplen=0, outlen=0; memset(outbuf,0x00,MAX_LEN); // header information step=in+1; memcpy(iv,step,IV_SIZE); // Extract the IV step+=IV_SIZE; memcpy(tag,step,16); // Extract the MAC step+=16; if (glob_key[0] == 0x00) // Generate key if its the first packet gen_key(); EVP_CIPHER_CTX *ctx; ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init (ctx); EVP_DecryptInit_ex (ctx, EVP_aes_256_gcm() , NULL, (const unsigned char *)glob_key, (const unsigned char *)iv); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, IV_SIZE, NULL); if (!EVP_DecryptUpdate (ctx, outbuf, &outlen, (const unsigned char *)step, len)) { fprintf(stderr, "[!] Error in EVP_DecryptUpdate()\n"); EVP_CIPHER_CTX_cleanup (ctx); return 0; } EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, sizeof(tag), tag); if (!EVP_DecryptFinal_ex (ctx, outbuf + outlen, &tmplen)) { fprintf(stderr, "[!] Error in EVP_DecryptFinal_ex(). Possible foul play involved.\n"); EVP_CIPHER_CTX_cleanup (ctx); return 0; } EVP_CIPHER_CTX_cleanup (ctx); memcpy(out,outbuf,outlen+tmplen); return len; }
int cipher_ctx_get_tag (EVP_CIPHER_CTX *ctx, uint8_t *tag_buf, int tag_size) { #ifdef HAVE_AEAD_CIPHER_MODES return EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_GET_TAG, tag_size, tag_buf); #else ASSERT (0); #endif }
static int s2n_composite_cipher_aes_sha256_set_mac_write_key(struct s2n_session_key *key, uint8_t *mac_key, uint32_t mac_size) { eq_check(mac_size, SHA256_DIGEST_LENGTH); EVP_CIPHER_CTX_ctrl(key->evp_cipher_ctx, EVP_CTRL_AEAD_SET_MAC_KEY, mac_size, mac_key); return 0; }
static int cipher_ctrl(hc_EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) { struct ossl_cipher_ctx *ossl_ctx = ctx->cipher_data; assert(ossl_ctx != NULL); return EVP_CIPHER_CTX_ctrl(ossl_ctx->ossl_cipher_ctx, type, arg, ptr); }
soter_status_t soter_sym_aead_decrypt_final(soter_sym_ctx_t *ctx, const void* auth_tag, const size_t auth_tag_length) { SOTER_CHECK_PARAM(auth_tag!=NULL); SOTER_CHECK_PARAM(auth_tag_length>=SOTER_AES_GCM_AUTH_TAG_LENGTH); SOTER_CHECK(ctx!=NULL); SOTER_IF_FAIL(EVP_CIPHER_CTX_ctrl(&(ctx->evp_sym_ctx), EVP_CTRL_GCM_SET_TAG, SOTER_AES_GCM_AUTH_TAG_LENGTH, (void*)auth_tag), soter_sym_aead_decrypt_destroy(ctx)); return soter_sym_aead_ctx_final(ctx, false); }
sgx_status_t sgx_aes_gcm128_enc_init(const uint8_t *key, const uint8_t *iv, uint32_t iv_len, const uint8_t *aad, uint32_t aad_len, sgx_aes_state_handle_t* aes_gcm_state) { if ((aad_len >= INT_MAX) || (key == NULL) || (iv_len != SGX_AESGCM_IV_SIZE) || ((aad_len > 0) && (aad == NULL)) || (iv == NULL) || (aes_gcm_state == NULL)) { return SGX_ERROR_INVALID_PARAMETER; } int len = 0; sgx_status_t ret = SGX_ERROR_UNEXPECTED; EVP_CIPHER_CTX * pState = NULL; do { // Create and initialise the context // if (!(pState = EVP_CIPHER_CTX_new())) { ret = SGX_ERROR_OUT_OF_MEMORY; break; } // Initialize ctx with AES-128 GCM // if (!EVP_EncryptInit_ex(pState, EVP_aes_128_gcm(), NULL, NULL, NULL)) { break; } // Set IV len // if (!EVP_CIPHER_CTX_ctrl(pState, EVP_CTRL_AEAD_SET_IVLEN, iv_len, NULL)) { break; } // Initialize encryption key and IV // if (!EVP_EncryptInit_ex(pState, NULL, NULL, (unsigned char*)key, iv)) { break; } // Provide AAD data if exist // if (NULL != aad) { if (!EVP_EncryptUpdate(pState, NULL, &len, aad, aad_len)) { break; } } *aes_gcm_state = (EVP_CIPHER_CTX*)pState; ret = SGX_SUCCESS; } while (0); if (ret != SGX_SUCCESS) { if (pState != NULL) { EVP_CIPHER_CTX_free(pState); } } return ret; }
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *aad, int aad_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext, unsigned char *tag) { EVP_CIPHER_CTX *ctx; int len; int ciphertext_len; /* Create and initialise the context */ if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); /* Initialise the encryption operation. */ if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) handleErrors(); /* Set IV length if default 12 bytes (96 bits) is not appropriate */ if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) handleErrors(); /* Initialise key and IV */ if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors(); /* Provide any AAD data. This can be called zero or more times as * required */ /* if(1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len)) handleErrors(); */ /* Provide the message to be encrypted, and obtain the encrypted output. * EVP_EncryptUpdate can be called multiple times if necessary */ if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) handleErrors(); ciphertext_len = len; /* Finalise the encryption. Normally ciphertext bytes may be written at * this stage, but this does not occur in GCM mode */ if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors(); ciphertext_len += len; /* Get the tag */ /* if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag)) handleErrors(); */ /* Clean up */ EVP_CIPHER_CTX_free(ctx); return ciphertext_len; }
/* * cipher_crypt() operates as following: * Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'. * Theses bytes are treated as additional authenticated data for * authenticated encryption modes. * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag. * This tag is written on encryption and verified on decryption. * Both 'aadlen' and 'authlen' can be set to 0. */ void cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len, u_int aadlen, u_int authlen) { if (authlen) { u_char lastiv[1]; if (authlen != cipher_authlen(cc->cipher)) fatal("%s: authlen mismatch %d", __func__, authlen); /* increment IV */ if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, 1, lastiv)) fatal("%s: EVP_CTRL_GCM_IV_GEN", __func__); /* set tag on decyption */ if (!cc->encrypt && !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG, authlen, __UNCONST(src + aadlen + len))) fatal("%s: EVP_CTRL_GCM_SET_TAG", __func__); } if (aadlen) { if (authlen && EVP_Cipher(&cc->evp, NULL, (const u_char *)src, aadlen) < 0) fatal("%s: EVP_Cipher(aad) failed", __func__); memcpy(dest, src, aadlen); } if (len % cc->cipher->block_size) fatal("%s: bad plaintext length %d", __func__, len); if (EVP_Cipher(&cc->evp, dest + aadlen, (const u_char *)src + aadlen, len) < 0) fatal("%s: EVP_Cipher failed", __func__); if (authlen) { /* compute tag (on encrypt) or verify tag (on decrypt) */ if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0) { if (cc->encrypt) fatal("%s: EVP_Cipher(final) failed", __func__); else fatal("Decryption integrity check failed"); } if (cc->encrypt && !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG, authlen, dest + aadlen + len)) fatal("%s: EVP_CTRL_GCM_GET_TAG", __func__); } }
int cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len) { const struct sshcipher *c = cc->cipher; #ifdef WITH_OPENSSL int evplen; #endif if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { if (len != 0) return SSH_ERR_INVALID_ARGUMENT; return 0; } if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { if (len != sizeof(cc->ac_ctx.ctr)) return SSH_ERR_INVALID_ARGUMENT; memcpy(iv, cc->ac_ctx.ctr, len); return 0; } if ((cc->cipher->flags & CFLAG_NONE) != 0) return 0; switch (c->number) { #ifdef WITH_OPENSSL case SSH_CIPHER_SSH2: case SSH_CIPHER_DES: case SSH_CIPHER_BLOWFISH: evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); if (evplen == 0) return 0; else if (evplen < 0) return SSH_ERR_LIBCRYPTO_ERROR; if ((u_int)evplen != len) return SSH_ERR_INVALID_ARGUMENT; #ifndef OPENSSL_HAVE_EVPCTR if (c->evptype == evp_aes_128_ctr) ssh_aes_ctr_iv(&cc->evp, 0, iv, len); else #endif if (cipher_authlen(c)) { if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, len, iv)) return SSH_ERR_LIBCRYPTO_ERROR; } else memcpy(iv, cc->evp.iv, len); break; #endif #ifdef WITH_SSH1 case SSH_CIPHER_3DES: return ssh1_3des_iv(&cc->evp, 0, iv, 24); #endif default: return SSH_ERR_INVALID_ARGUMENT; } return 0; }
/* * aes_gcm_openssl_set_iv(c, iv) sets the counter value to the exor of iv with * the offset */ err_status_t aes_gcm_openssl_set_iv (aes_gcm_ctx_t *c, void *iv, int direction) { const EVP_CIPHER *evp; v128_t *nonce = iv; if (direction != direction_encrypt && direction != direction_decrypt) { return (err_status_bad_param); } c->dir = direction; debug_print(mod_aes_gcm, "setting iv: %s", v128_hex_string(nonce)); switch (c->key_size) { case AES_256_KEYSIZE: evp = EVP_aes_256_gcm(); break; case AES_128_KEYSIZE: evp = EVP_aes_128_gcm(); break; default: return (err_status_bad_param); break; } if (!EVP_CipherInit_ex(&c->ctx, evp, NULL, (const unsigned char*)&c->key.v8, NULL, (c->dir == direction_encrypt ? 1 : 0))) { return (err_status_init_fail); } /* set IV len and the IV value, the followiong 3 calls are required */ if (!EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0)) { return (err_status_init_fail); } if (!EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_SET_IV_FIXED, -1, iv)) { return (err_status_init_fail); } if (!EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_IV_GEN, 0, iv)) { return (err_status_init_fail); } return (err_status_ok); }
static int rc2_meth_to_magic(EVP_CIPHER_CTX *e) { int i; EVP_CIPHER_CTX_ctrl(e, EVP_CTRL_GET_RC2_KEY_BITS, 0, &i); if (i == 128) return(RC2_128_MAGIC); else if (i == 64) return(RC2_64_MAGIC); else if (i == 40) return(RC2_40_MAGIC); else return(0); }
static int aria_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len) { EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,ctx); int rv = -1; /* Encrypt/decrypt must be performed in place */ if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN)) return -1; /* * Set IV from start of buffer or generate IV and write to start of * buffer. */ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CIPHER_CTX_encrypting(ctx) ? EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV, EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0) goto err; /* Use saved AAD */ if (CRYPTO_gcm128_aad(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), gctx->tls_aad_len)) goto err; /* Fix buffer and length to point to payload */ in += EVP_GCM_TLS_EXPLICIT_IV_LEN; out += EVP_GCM_TLS_EXPLICIT_IV_LEN; len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; if (EVP_CIPHER_CTX_encrypting(ctx)) { /* Encrypt payload */ if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len)) goto err; out += len; /* Finally write tag */ CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN); rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; } else { /* Decrypt */ if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len)) goto err; /* Retrieve tag */ CRYPTO_gcm128_tag(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), EVP_GCM_TLS_TAG_LEN); /* If tag mismatch wipe buffer */ if (CRYPTO_memcmp(EVP_CIPHER_CTX_buf_noconst(ctx), in + len, EVP_GCM_TLS_TAG_LEN)) { OPENSSL_cleanse(out, len); goto err; } rv = len; } err: gctx->iv_set = 0; gctx->tls_aad_len = -1; return rv; }
soter_status_t soter_sym_aead_encrypt_final(soter_sym_ctx_t *ctx, void* auth_tag, size_t* auth_tag_length){ SOTER_CHECK_PARAM(auth_tag!=NULL); if((*auth_tag_length)<SOTER_AES_GCM_AUTH_TAG_LENGTH){ (*auth_tag_length)=SOTER_AES_GCM_AUTH_TAG_LENGTH; return SOTER_BUFFER_TOO_SMALL; } SOTER_CHECK(soter_sym_aead_ctx_final(ctx, true)==SOTER_SUCCESS); SOTER_CHECK(EVP_CIPHER_CTX_ctrl(&(ctx->evp_sym_ctx), EVP_CTRL_GCM_GET_TAG, SOTER_AES_GCM_AUTH_TAG_LENGTH, auth_tag)); (*auth_tag_length)=SOTER_AES_GCM_AUTH_TAG_LENGTH; return SOTER_SUCCESS; }
int Decrypt_AesGcm128(const uint8_t * cipher_text, uint32_t cipher_text_len, const SecureString & key, string & plain_text){ EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); EVP_CIPHER * cipher=EVP_aes_128_gcm(); if(1 != EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) return false; if(1 != EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, GCM_NONCE_LENGTH, NULL)) return false; unsigned char nonce[GCM_NONCE_LENGTH]={}; if(1 != EVP_EncryptInit_ex(&ctx, NULL, NULL, key.data(), cipher_text)) return false; int outl=out.size(); const int ret = EVP_CipherUpdate(&ctx,&out[0],outl,&in[0],in.size()); if(1==ret){ out.resize(outl); return true; } out.resize(EVP_CIPHER_CTX_block_size(&ctx)); /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag)) return false; if(1 != EVP_CipherFinal_ex(&ctx,out.data(),outl) ){ return false; } out.resize(outl); return OK; }
size_t crypto_encrypt_buffer(const char *in, size_t inlen, char *out, size_t outlen) { EVP_CIPHER_CTX ctx; uint8_t iv[IV_SIZE]; uint8_t tag[GCM_TAG_SIZE]; uint8_t version = API_VERSION; off_t sz; int olen; int len = 0; int ret = 0; /* output buffer does not have enough room */ if (outlen < inlen + sizeof version + sizeof tag + sizeof iv) return 0; /* input should not exceed 64GB */ sz = inlen; if (sz >= 0x1000000000LL) return 0; /* prepend version */ *out = version; len++; /* generate IV */ memset(iv, 0, sizeof iv); arc4random_buf(iv, sizeof iv); memcpy(out + len, iv, sizeof iv); len += sizeof iv; EVP_CIPHER_CTX_init(&ctx); EVP_EncryptInit_ex(&ctx, EVP_aes_256_gcm(), NULL, cp.key, iv); /* encrypt buffer */ if (!EVP_EncryptUpdate(&ctx, out + len, &olen, in, inlen)) goto end; len += olen; /* finalize and write last chunk if any */ if (!EVP_EncryptFinal_ex(&ctx, out + len, &olen)) goto end; len += olen; /* get and append tag */ EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, sizeof tag, tag); memcpy(out + len, tag, sizeof tag); ret = len + sizeof tag; end: EVP_CIPHER_CTX_cleanup(&ctx); return ret; }
JNIEXPORT void JNICALL Java_com_intel_diceros_crypto_engines_AESOpensslEngine_getTag( JNIEnv *env, jobject object, jlong cipherContext, jbyteArray out, jint outOff, jint tLen) { unsigned char * tagOut = (unsigned char *) (*env)->GetByteArrayElements(env, out, 0); CipherContext* cipherCtx = (CipherContext*) cipherContext; EVP_CIPHER_CTX * ctx = (EVP_CIPHER_CTX *) cipherCtx->opensslCtx; EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tLen, tagOut + outOff); (*env)->ReleaseByteArrayElements(env, out, (jbyte *) tagOut, 0); }