/* * call-seq: * cipher.iv = string -> string * * Sets the cipher IV. Please note that since you should never be using ECB * mode, an IV is always explicitly required and should be set prior to * encryption. The IV itself can be safely transmitted in public, but it * should be unpredictable to prevent certain kinds of attacks. You may use * Cipher#random_iv to create a secure random IV. * * Only call this method after calling Cipher#encrypt or Cipher#decrypt. * * If not explicitly set, the OpenSSL default of an all-zeroes ("\\0") IV is * used. */ static VALUE ossl_cipher_set_iv(VALUE self, VALUE iv) { EVP_CIPHER_CTX *ctx; StringValue(iv); GetCipher(self, ctx); if (RSTRING_LEN(iv) < EVP_CIPHER_CTX_iv_length(ctx)) ossl_raise(eCipherError, "iv length too short"); if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, (unsigned char *)RSTRING_PTR(iv), -1) != 1) ossl_raise(eCipherError, NULL); return iv; }
/* * Exports an IV from the sshcipher_ctx required to export the key * state back from the unprivileged child to the privileged parent * process. */ int cipher_get_keyiv_len(const struct sshcipher_ctx *cc) { const struct sshcipher *c = cc->cipher; int ivlen = 0; if (c->number == SSH_CIPHER_3DES) ivlen = 24; else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) ivlen = 0; #ifdef WITH_OPENSSL else ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp); #endif /* WITH_OPENSSL */ return (ivlen); }
bool crypt_openssl::decode(unsigned char *datain, int lenin, unsigned char *dataout, int lenout) { EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, NULL, NULL); OPENSSL_assert(EVP_CIPHER_CTX_key_length(ctx) == 16); OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == 16); EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv); if(!EVP_DecryptUpdate(ctx, dataout, &lenout, datain, lenin)) { return false; } if(!EVP_EncryptFinal_ex(ctx, dataout, &lenout)) { return false; } }
int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) { int i = 0; unsigned int l; if (type != NULL) { l = EVP_CIPHER_CTX_iv_length(c); OPENSSL_assert(l <= sizeof(c->iv)); i = ASN1_TYPE_get_octetstring(type, c->oiv, l); if (i != (int)l) return (-1); else if (i > 0) memcpy(c->iv, c->oiv, l); } return (i); }
void cipher_set_keyiv(CipherContext *cc, u_char *iv) { Cipher *c = cc->cipher; u_char *div = NULL; 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 OPENSSL_VERSION_NUMBER < 0x00907000L if (c->evptype == evp_rijndael) { struct ssh_rijndael_ctx *aesc; aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp); if (aesc == NULL) fatal("%s: no rijndael context", __func__); div = aesc->r_iv; } else #endif { div = cc->evp.iv; } break; case SSH_CIPHER_3DES: { struct ssh1_3des_ctx *desc; desc = EVP_CIPHER_CTX_get_app_data(&cc->evp); if (desc == NULL) fatal("%s: no 3des context", __func__); debug3("%s: Installed 3DES IV", __func__); memcpy(desc->k1.iv, iv, 8); memcpy(desc->k2.iv, iv + 8, 8); memcpy(desc->k3.iv, iv + 16, 8); return; } default: fatal("%s: bad cipher %d", __func__, c->number); } memcpy(div, iv, evplen); }
int csf_ctx_init(CSF_CTX **ctx_out, int *fh, unsigned char *key_data, int key_sz, int page_sz) { EVP_CIPHER_CTX ectx; CSF_CTX *ctx; ctx = csf_malloc(sizeof(CSF_CTX)); ctx->seek_ptr = ctx->file_sz = 0; ctx->fh = fh; ctx->key_sz = key_sz; ctx->key_data = csf_malloc(ctx->key_sz); memcpy(ctx->key_data, key_data, ctx->key_sz); EVP_EncryptInit(&ectx, CIPHER, ctx->key_data, NULL); ctx->block_sz = EVP_CIPHER_CTX_block_size(&ectx); ctx->iv_sz = EVP_CIPHER_CTX_iv_length(&ectx); /* the combined page size includes the size of the initialization vector, an integer for the count of bytes on page, and the data block */ ctx->page_sz = page_sz; /* ensure the page header allocation ends on an even block alignment */ ctx->page_header_sz = (sizeof(CSF_PAGE_HEADER) % ctx->block_sz == 0) ? (sizeof(CSF_PAGE_HEADER) / ctx->block_sz) : (sizeof(CSF_PAGE_HEADER) / ctx->block_sz) + ctx->block_sz; /* determine unused space avaliable for data */ ctx->data_sz = ctx->page_sz - ctx->iv_sz - ctx->page_header_sz; assert(ctx->iv_sz % ctx->block_sz == 0); assert(ctx->page_header_sz % ctx->block_sz == 0); assert(ctx->data_sz % ctx->block_sz == 0); assert(ctx->page_sz % ctx->block_sz == 0); ctx->page_buffer = csf_malloc(ctx->page_sz); ctx->csf_buffer = csf_malloc(ctx->page_sz); ctx->scratch_buffer = csf_malloc(ctx->page_sz); EVP_CIPHER_CTX_cleanup(&ectx); ctx->encrypted=1; TRACE6("csf_init() ctx->data_sz=%d, ctx->page_sz=%d, ctx->block_sz=%d, ctx->iv_sz=%d, ctx->key_sz=%d\n", ctx->data_sz, ctx->page_sz, ctx->block_sz, ctx->iv_sz, ctx->key_sz); *ctx_out = ctx; return 0; }
bool CryptFileDevice::initCipher() { const EVP_CIPHER *cipher = EVP_enc_null(); if (m_aesKeyLength == kAesKeyLength128) cipher = EVP_aes_128_ctr(); else if (m_aesKeyLength == kAesKeyLength192) cipher = EVP_aes_192_ctr(); else if (m_aesKeyLength == kAesKeyLength256) cipher = EVP_aes_256_ctr(); else Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown value of AesKeyLength"); EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); EVP_EncryptInit_ex(&ctx, cipher, NULL, NULL, NULL); int keyLength = EVP_CIPHER_CTX_key_length(&ctx); int ivLength = EVP_CIPHER_CTX_iv_length(&ctx); unsigned char key[keyLength]; unsigned char iv[ivLength]; int ok = EVP_BytesToKey(cipher, EVP_sha256(), m_salt.isEmpty() ? NULL : (unsigned char *)m_salt.data(), (unsigned char *)m_password.data(), m_password.length(), m_numRounds, key, iv); EVP_CIPHER_CTX_cleanup(&ctx); if (ok == 0) return false; int res = AES_set_encrypt_key(key, keyLength * 8, &m_aesKey); if (res != 0) return false; initCtr(&m_ctrState, iv); return true; }
void cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) { const Cipher *c = cc->cipher; int evplen; if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { if (len != 0) fatal("%s: wrong iv length %d != %d", __func__, len, 0); return; } switch (c->number) { #ifdef NONE_CIPHER_ENABLED case SSH_CIPHER_NONE: #endif 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); #ifdef USE_BUILTIN_RIJNDAEL if (c->evptype == evp_rijndael) ssh_rijndael_iv(&cc->evp, 0, iv, len); else #endif #ifndef OPENSSL_HAVE_EVPCTR if (c->evptype == evp_aes_128_ctr) ssh_aes_ctr_iv(&cc->evp, 0, iv, len); else #endif 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_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, size_t len) { #ifdef WITH_OPENSSL const struct sshcipher *c = cc->cipher; 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; #ifdef WITH_OPENSSL evplen = EVP_CIPHER_CTX_iv_length(cc->evp); if (evplen == 0) return 0; else if (evplen < 0) return SSH_ERR_LIBCRYPTO_ERROR; if ((size_t)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 if (!EVP_CIPHER_CTX_get_iv(cc->evp, iv, len)) return SSH_ERR_LIBCRYPTO_ERROR; #endif return 0; }
static int sms4_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_SMS4_WRAP_CTX *wctx = EVP_C_DATA(EVP_SMS4_WRAP_CTX,ctx); if (!iv && !key) return 1; if (key) { if (EVP_CIPHER_CTX_encrypting(ctx)) sms4_set_encrypt_key(&wctx->ks.ks, key); else sms4_set_decrypt_key(&wctx->ks.ks, key); if (!iv) wctx->iv = NULL; } if (iv) { memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, EVP_CIPHER_CTX_iv_length(ctx)); wctx->iv = EVP_CIPHER_CTX_iv_noconst(ctx); } return 1; }
int cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv) { const struct sshcipher *c = cc->cipher; #ifdef WITH_OPENSSL int evplen = 0; #endif if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) return 0; if ((cc->cipher->flags & CFLAG_NONE) != 0) return 0; switch (c->number) { #ifdef WITH_OPENSSL case SSH_CIPHER_NONE: case SSH_CIPHER_SSH2: case SSH_CIPHER_DES: case SSH_CIPHER_BLOWFISH: 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(cc->evp->iv, iv, evplen); break; #endif #ifdef WITH_SSH1 case SSH_CIPHER_3DES: return ssh1_3des_iv(cc->evp, 1, __UNCONST(iv), 24); #endif default: return SSH_ERR_INVALID_ARGUMENT; } return 0; }
int encrypt(unsigned char* buf_in, int buf_in_len, unsigned char* buf_out, int* buf_out_len, unsigned char* key, int key_len){ int outlen; EVP_CIPHER_CTX ctx; pad_space(key, key_len); unsigned char iv[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; EVP_CIPHER_CTX_init(&ctx); EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), NULL, NULL, NULL, DO_ENCRYPT); OPENSSL_assert(EVP_CIPHER_CTX_key_length(&ctx) == 16); OPENSSL_assert(EVP_CIPHER_CTX_iv_length(&ctx) == 16); EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, DO_ENCRYPT); EVP_CipherUpdate(&ctx, buf_out, &outlen, buf_in, buf_in_len); *buf_out_len = outlen; EVP_CipherFinal_ex(&ctx, buf_out + outlen, &outlen); *buf_out_len += outlen; EVP_CIPHER_CTX_cleanup(&ctx); return 1; }
static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) { long num=0; int i=0,l; int key_bits; unsigned char iv[EVP_MAX_IV_LENGTH]; if (type != NULL) { l=EVP_CIPHER_CTX_iv_length(c); i=ASN1_TYPE_get_int_octetstring(type,&num,iv,l); if (i != l) return(-1); key_bits =rc2_magic_to_meth((int)num); if (!key_bits) return(-1); if(i > 0) EVP_CipherInit(c, NULL, NULL, iv, -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); }
int do_crypt(Bank *bank, unsigned char *inbuf, unsigned char *res, int do_encrypt) { unsigned char outbuf[10000 + EVP_MAX_BLOCK_LENGTH]; int outlen, len, inlen = strlen((char*)inbuf); EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), NULL, NULL, NULL, do_encrypt); OPENSSL_assert(EVP_CIPHER_CTX_key_length(&ctx) == 16); OPENSSL_assert(EVP_CIPHER_CTX_iv_length(&ctx) == 16); EVP_CipherInit_ex(&ctx, NULL, NULL, bank->key, bank->iv, do_encrypt); if(!EVP_CipherUpdate(&ctx, outbuf, &outlen, inbuf, inlen)) { EVP_CIPHER_CTX_cleanup(&ctx); return 0; } memcpy(res, outbuf, outlen); len = outlen; if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen)) { EVP_CIPHER_CTX_cleanup(&ctx); return 0; } memcpy(res+len, outbuf, outlen); len += outlen; EVP_CIPHER_CTX_cleanup(&ctx); return len; }
int cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv) { struct sshcipher *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 SSH_ERR_LIBCRYPTO_ERROR; if (c->evptype == evp_aes_128_ctr) return ssh_aes_ctr_iv(&cc->evp, 1, (u_char *)iv, evplen); else memcpy(cc->evp.iv, iv, evplen); return 0; case SSH_CIPHER_3DES: return ssh1_3des_iv(&cc->evp, 1, (u_char *)iv, 24); default: return SSH_ERR_INVALID_ARGUMENT; } }
BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec) { BIO *b; EVP_CIPHER_CTX *ctx; const EVP_CIPHER *ciph; X509_ALGOR *calg = ec->contentEncryptionAlgorithm; unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL; unsigned char *tkey = NULL; size_t tkeylen = 0; int ok = 0; int enc, keep_key = 0; enc = ec->cipher ? 1 : 0; b = BIO_new(BIO_f_cipher()); if (!b) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE); return NULL; } BIO_get_cipher_ctx(b, &ctx); if (enc) { ciph = ec->cipher; /* * If not keeping key set cipher to NULL so subsequent calls decrypt. */ if (ec->key) ec->cipher = NULL; } else { ciph = EVP_get_cipherbyobj(calg->algorithm); if (!ciph) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_UNKNOWN_CIPHER); goto err; } } if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_CIPHER_INITIALISATION_ERROR); goto err; } if (enc) { int ivlen; calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx)); /* Generate a random IV if we need one */ ivlen = EVP_CIPHER_CTX_iv_length(ctx); if (ivlen > 0) { if (RAND_bytes(iv, ivlen) <= 0) goto err; piv = iv; } } else if (EVP_CIPHER_asn1_to_param(ctx, calg->parameter) <= 0) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); goto err; } tkeylen = EVP_CIPHER_CTX_key_length(ctx); /* Generate random session key */ if (!enc || !ec->key) { tkey = OPENSSL_malloc(tkeylen); if (!tkey) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE); goto err; } if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0) goto err; } if (!ec->key) { ec->key = tkey; ec->keylen = tkeylen; tkey = NULL; if (enc) keep_key = 1; else ERR_clear_error(); } if (ec->keylen != tkeylen) { /* If necessary set key length */ if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0) { /* * Only reveal failure if debugging so we don't leak information * which may be useful in MMA. */ if (enc || ec->debug) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_INVALID_KEY_LENGTH); goto err; } else { /* Use random key */ OPENSSL_clear_free(ec->key, ec->keylen); ec->key = tkey; ec->keylen = tkeylen; tkey = NULL; ERR_clear_error(); } } } if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_CIPHER_INITIALISATION_ERROR); goto err; } if (piv) { calg->parameter = ASN1_TYPE_new(); if (!calg->parameter) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE); goto err; } if (EVP_CIPHER_param_to_asn1(ctx, calg->parameter) <= 0) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); goto err; } } ok = 1; err: if (!keep_key) { OPENSSL_clear_free(ec->key, ec->keylen); ec->key = NULL; } OPENSSL_clear_free(tkey, tkeylen); if (ok) return b; BIO_free(b); return NULL; }
/* tls_decrypt_ticket attempts to decrypt a session ticket. * * etick: points to the body of the session ticket extension. * eticklen: the length of the session tickets extenion. * sess_id: points at the session ID. * sesslen: the length of the session ID. * psess: (output) on return, if a ticket was decrypted, then this is set to * point to the resulting session. * * Returns: * -1: fatal error, either from parsing or decrypting the ticket. * 2: the ticket couldn't be decrypted. * 3: a ticket was successfully decrypted and *psess was set. * 4: same as 3, but the ticket needs to be renewed. */ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, const unsigned char *sess_id, int sesslen, SSL_SESSION **psess) { SSL_SESSION *sess; unsigned char *sdec; const unsigned char *p; int slen, mlen, renew_ticket = 0; unsigned char tick_hmac[EVP_MAX_MD_SIZE]; HMAC_CTX hctx; EVP_CIPHER_CTX ctx; SSL_CTX *tctx = s->initial_ctx; /* * The API guarantees EVP_MAX_IV_LENGTH bytes of space for * the iv to tlsext_ticket_key_cb(). Since the total space * required for a session cookie is never less than this, * this check isn't too strict. The exact check comes later. */ if (eticklen < 16 + EVP_MAX_IV_LENGTH) return 2; /* Initialize session ticket encryption and HMAC contexts */ HMAC_CTX_init(&hctx); EVP_CIPHER_CTX_init(&ctx); if (tctx->internal->tlsext_ticket_key_cb) { unsigned char *nctick = (unsigned char *)etick; int rv = tctx->internal->tlsext_ticket_key_cb(s, nctick, nctick + 16, &ctx, &hctx, 0); if (rv < 0) { HMAC_CTX_cleanup(&hctx); EVP_CIPHER_CTX_cleanup(&ctx); return -1; } if (rv == 0) { HMAC_CTX_cleanup(&hctx); EVP_CIPHER_CTX_cleanup(&ctx); return 2; } if (rv == 2) renew_ticket = 1; } else { /* Check key name matches */ if (timingsafe_memcmp(etick, tctx->internal->tlsext_tick_key_name, 16)) return 2; HMAC_Init_ex(&hctx, tctx->internal->tlsext_tick_hmac_key, 16, tlsext_tick_md(), NULL); EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, tctx->internal->tlsext_tick_aes_key, etick + 16); } /* * Attempt to process session ticket, first conduct sanity and * integrity checks on ticket. */ mlen = HMAC_size(&hctx); if (mlen < 0) { HMAC_CTX_cleanup(&hctx); EVP_CIPHER_CTX_cleanup(&ctx); return -1; } /* Sanity check ticket length: must exceed keyname + IV + HMAC */ if (eticklen <= 16 + EVP_CIPHER_CTX_iv_length(&ctx) + mlen) { HMAC_CTX_cleanup(&hctx); EVP_CIPHER_CTX_cleanup(&ctx); return 2; } eticklen -= mlen; /* Check HMAC of encrypted ticket */ if (HMAC_Update(&hctx, etick, eticklen) <= 0 || HMAC_Final(&hctx, tick_hmac, NULL) <= 0) { HMAC_CTX_cleanup(&hctx); EVP_CIPHER_CTX_cleanup(&ctx); return -1; } HMAC_CTX_cleanup(&hctx); if (timingsafe_memcmp(tick_hmac, etick + eticklen, mlen)) { EVP_CIPHER_CTX_cleanup(&ctx); return 2; } /* Attempt to decrypt session data */ /* Move p after IV to start of encrypted ticket, update length */ p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx); eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx); sdec = malloc(eticklen); if (sdec == NULL || EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen) <= 0) { free(sdec); EVP_CIPHER_CTX_cleanup(&ctx); return -1; } if (EVP_DecryptFinal_ex(&ctx, sdec + slen, &mlen) <= 0) { free(sdec); EVP_CIPHER_CTX_cleanup(&ctx); return 2; } slen += mlen; EVP_CIPHER_CTX_cleanup(&ctx); p = sdec; sess = d2i_SSL_SESSION(NULL, &p, slen); free(sdec); if (sess) { /* The session ID, if non-empty, is used by some clients to * detect that the ticket has been accepted. So we copy it to * the session structure. If it is empty set length to zero * as required by standard. */ if (sesslen) memcpy(sess->session_id, sess_id, sesslen); sess->session_id_length = sesslen; *psess = sess; if (renew_ticket) return 4; else return 3; } ERR_clear_error(); /* For session parse failure, indicate that we need to send a new * ticket. */ return 2; }
bool crypto_aes_decrypt(struct string *ciphertext, struct string *aes_key, struct string *aes_iv, struct string *decrypted) { bool retval = false; EVP_CIPHER_CTX ctx; int decryptspace; int decryptdone; EVP_CIPHER_CTX_init(&ctx); if (!EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, (unsigned char *)string_get(aes_key), (unsigned char *)string_get(aes_iv))) { log_err("crypto_aes_decrypt: init failed\n"); ERR_print_errors_fp(stderr); goto bail_out; } EVP_CIPHER_CTX_set_padding(&ctx, 1); if (string_length(aes_key) != EVP_CIPHER_CTX_key_length(&ctx)) { log_err("crypto_aes_decrypt: invalid key size (%" PRIuPTR " vs expected %d)\n", string_length(aes_key), EVP_CIPHER_CTX_key_length(&ctx)); goto bail_out; } if (string_length(aes_iv) != EVP_CIPHER_CTX_iv_length(&ctx)) { log_err("crypto_aes_decrypt: invalid iv size (%" PRIuPTR " vs expected %d)\n", string_length(aes_iv), EVP_CIPHER_CTX_iv_length(&ctx)); goto bail_out; } decryptspace = string_length(ciphertext) + EVP_MAX_BLOCK_LENGTH; string_free(decrypted); /* free previous buffer */ string_init(decrypted, decryptspace, 1024); if (string_size(decrypted) < decryptspace) { log_err("crypto_aes_decrypt: decrypt buffer malloc error\n"); goto bail_out; } if (EVP_DecryptUpdate(&ctx, (unsigned char*)string_get(decrypted), &decryptdone, (unsigned char*)string_get(ciphertext), string_length(ciphertext))) { /* TODO: need cleaner way: */ decrypted->_u._s.length = decryptdone; } else { log_err("crypto_aes_decrypt: decrypt failed\n"); ERR_print_errors_fp(stderr); goto bail_out; } if (EVP_DecryptFinal_ex(&ctx, (unsigned char*)string_get(decrypted)+string_length(decrypted), &decryptdone)) { /* TODO: need cleaner way: */ decrypted->_u._s.length += decryptdone; } else { log_err("crypto_aes_decrypt: decrypt final failed\n"); ERR_print_errors_fp(stderr); goto bail_out; } retval = true; bail_out: EVP_CIPHER_CTX_cleanup(&ctx); return retval; }
int cipher_ctx_iv_length (const EVP_CIPHER_CTX *ctx) { return EVP_CIPHER_CTX_iv_length (ctx); }
static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, const unsigned char *sess_id, int sesslen, SSL_SESSION **psess) { SSL_SESSION *sess; unsigned char *sdec; const unsigned char *p; int slen, mlen, renew_ticket = 0; unsigned char tick_hmac[EVP_MAX_MD_SIZE]; HMAC_CTX hctx; EVP_CIPHER_CTX ctx; SSL_CTX *tctx = s->initial_ctx; /* Need at least keyname + iv + some encrypted data */ if (eticklen < 48) goto tickerr; /* Initialize session ticket encryption and HMAC contexts */ HMAC_CTX_init(&hctx); EVP_CIPHER_CTX_init(&ctx); if (tctx->tlsext_ticket_key_cb) { unsigned char *nctick = (unsigned char *)etick; int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16, &ctx, &hctx, 0); if (rv < 0) return -1; if (rv == 0) goto tickerr; if (rv == 2) renew_ticket = 1; } else { /* Check key name matches */ if (memcmp(etick, tctx->tlsext_tick_key_name, 16)) goto tickerr; HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(), NULL); EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, tctx->tlsext_tick_aes_key, etick + 16); } /* Attempt to process session ticket, first conduct sanity and * integrity checks on ticket. */ mlen = HMAC_size(&hctx); eticklen -= mlen; /* Check HMAC of encrypted ticket */ HMAC_Update(&hctx, etick, eticklen); HMAC_Final(&hctx, tick_hmac, NULL); HMAC_CTX_cleanup(&hctx); if (memcmp(tick_hmac, etick + eticklen, mlen)) goto tickerr; /* Attempt to decrypt session data */ /* Move p after IV to start of encrypted ticket, update length */ p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx); eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx); sdec = OPENSSL_malloc(eticklen); if (!sdec) { EVP_CIPHER_CTX_cleanup(&ctx); return -1; } EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen); if (EVP_DecryptFinal(&ctx, sdec + slen, &mlen) <= 0) goto tickerr; slen += mlen; EVP_CIPHER_CTX_cleanup(&ctx); p = sdec; sess = d2i_SSL_SESSION(NULL, &p, slen); OPENSSL_free(sdec); if (sess) { /* The session ID if non-empty is used by some clients to * detect that the ticket has been accepted. So we copy it to * the session structure. If it is empty set length to zero * as required by standard. */ if (sesslen) memcpy(sess->session_id, sess_id, sesslen); sess->session_id_length = sesslen; *psess = sess; s->tlsext_ticket_expected = renew_ticket; return 1; } /* If session decrypt failure indicate a cache miss and set state to * send a new ticket */ tickerr: s->tlsext_ticket_expected = 1; return 0; }
static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { int ciphertype; int ret; afalg_ctx *actx; char ciphername[ALG_MAX_SALG_NAME]; if (ctx == NULL || key == NULL) { ALG_WARN("%s: Null Parameter\n", __func__); return 0; } if (EVP_CIPHER_CTX_cipher(ctx) == NULL) { ALG_WARN("%s: Cipher object NULL\n", __func__); return 0; } actx = EVP_CIPHER_CTX_get_cipher_data(ctx); if (actx == NULL) { ALG_WARN("%s: Cipher data NULL\n", __func__); return 0; } ciphertype = EVP_CIPHER_CTX_nid(ctx); switch (ciphertype) { case NID_aes_128_cbc: strncpy(ciphername, "cbc(aes)", ALG_MAX_SALG_NAME); break; default: ALG_WARN("%s: Unsupported Cipher type %d\n", __func__, ciphertype); return 0; } ciphername[ALG_MAX_SALG_NAME-1]='\0'; if (ALG_AES_IV_LEN != EVP_CIPHER_CTX_iv_length(ctx)) { ALG_WARN("%s: Unsupported IV length :%d\n", __func__, EVP_CIPHER_CTX_iv_length(ctx)); return 0; } /* Setup AFALG socket for crypto processing */ ret = afalg_create_sk(actx, "skcipher", ciphername); if (ret < 1) return 0; ret = afalg_set_key(actx, key, EVP_CIPHER_CTX_key_length(ctx)); if (ret < 1) goto err; /* Setup AIO ctx to allow async AFALG crypto processing */ if (afalg_init_aio(&actx->aio) == 0) goto err; # ifdef ALG_ZERO_COPY pipe(actx->zc_pipe); # endif actx->init_done = MAGIC_INIT_NUM; return 1; err: close(actx->sfd); close(actx->bfd); return 0; }
/*- * tls13_enc encrypts/decrypts |n_recs| in |recs|. * * Returns: * 0: (in non-constant time) if the record is publically invalid (i.e. too * short etc). * 1: if the record encryption was successful. * -1: if the record's AEAD-authenticator is invalid or, if sending, * an internal error occurred. */ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending) { EVP_CIPHER_CTX *ctx; unsigned char iv[EVP_MAX_IV_LENGTH]; size_t ivlen, taglen, offset, loop; unsigned char *staticiv; unsigned char *seq; int lenu, lenf; SSL3_RECORD *rec = &recs[0]; uint32_t alg_enc; if (n_recs != 1) { /* Should not happen */ /* TODO(TLS1.3): Support pipelining */ return -1; } if (sending) { ctx = s->enc_write_ctx; staticiv = s->write_iv; seq = RECORD_LAYER_get_write_sequence(&s->rlayer); } else { ctx = s->enc_read_ctx; staticiv = s->read_iv; seq = RECORD_LAYER_get_read_sequence(&s->rlayer); } if (ctx == NULL) { memmove(rec->data, rec->input, rec->length); rec->input = rec->data; return 1; } ivlen = EVP_CIPHER_CTX_iv_length(ctx); if (s->early_data_state == SSL_EARLY_DATA_WRITING || s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) { alg_enc = s->session->cipher->algorithm_enc; } else { /* * To get here we must have selected a ciphersuite - otherwise ctx would * be NULL */ assert(s->s3->tmp.new_cipher != NULL); if (s->s3->tmp.new_cipher == NULL) return -1; alg_enc = s->s3->tmp.new_cipher->algorithm_enc; } if (alg_enc & SSL_AESCCM) { if (alg_enc & (SSL_AES128CCM8 | SSL_AES256CCM8)) taglen = EVP_CCM8_TLS_TAG_LEN; else taglen = EVP_CCM_TLS_TAG_LEN; if (sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, NULL) <= 0) return -1; } else if (alg_enc & SSL_AESGCM) { taglen = EVP_GCM_TLS_TAG_LEN; } else if (alg_enc & SSL_CHACHA20) { taglen = EVP_CHACHAPOLY_TLS_TAG_LEN; } else { return -1; } if (!sending) { /* * Take off tag. There must be at least one byte of content type as * well as the tag */ if (rec->length < taglen + 1) return 0; rec->length -= taglen; } /* Set up IV */ if (ivlen < SEQ_NUM_SIZE) { /* Should not happen */ return -1; } offset = ivlen - SEQ_NUM_SIZE; memcpy(iv, staticiv, offset); for (loop = 0; loop < SEQ_NUM_SIZE; loop++) iv[offset + loop] = staticiv[offset + loop] ^ seq[loop]; /* Increment the sequence counter */ for (loop = SEQ_NUM_SIZE; loop > 0; loop--) { ++seq[loop - 1]; if (seq[loop - 1] != 0) break; } if (loop == 0) { /* Sequence has wrapped */ return -1; } /* TODO(size_t): lenu/lenf should be a size_t but EVP doesn't support it */ if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, sending) <= 0 || (!sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, rec->data + rec->length) <= 0) || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, (unsigned int)rec->length) <= 0 || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 || (size_t)(lenu + lenf) != rec->length) { return -1; } if (sending) { /* Add the tag */ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen, rec->data + rec->length) <= 0) return -1; rec->length += taglen; } return 1; }
/*- * tls13_enc encrypts/decrypts |n_recs| in |recs|. Will call SSLfatal() for * internal errors, but not otherwise. * * Returns: * 0: (in non-constant time) if the record is publically invalid (i.e. too * short etc). * 1: if the record encryption was successful. * -1: if the record's AEAD-authenticator is invalid or, if sending, * an internal error occurred. */ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending) { EVP_CIPHER_CTX *ctx; unsigned char iv[EVP_MAX_IV_LENGTH], recheader[SSL3_RT_HEADER_LENGTH]; size_t ivlen, taglen, offset, loop, hdrlen; unsigned char *staticiv; unsigned char *seq; int lenu, lenf; SSL3_RECORD *rec = &recs[0]; uint32_t alg_enc; WPACKET wpkt; if (n_recs != 1) { /* Should not happen */ /* TODO(TLS1.3): Support pipelining */ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, ERR_R_INTERNAL_ERROR); return -1; } if (sending) { ctx = s->enc_write_ctx; staticiv = s->write_iv; seq = RECORD_LAYER_get_write_sequence(&s->rlayer); } else { ctx = s->enc_read_ctx; staticiv = s->read_iv; seq = RECORD_LAYER_get_read_sequence(&s->rlayer); } /* * If we're sending an alert and ctx != NULL then we must be forcing * plaintext alerts. If we're reading and ctx != NULL then we allow * plaintext alerts at certain points in the handshake. If we've got this * far then we have already validated that a plaintext alert is ok here. */ if (ctx == NULL || rec->type == SSL3_RT_ALERT) { memmove(rec->data, rec->input, rec->length); rec->input = rec->data; return 1; } ivlen = EVP_CIPHER_CTX_iv_length(ctx); if (s->early_data_state == SSL_EARLY_DATA_WRITING || s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) { if (s->session != NULL && s->session->ext.max_early_data > 0) { alg_enc = s->session->cipher->algorithm_enc; } else { if (!ossl_assert(s->psksession != NULL && s->psksession->ext.max_early_data > 0)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, ERR_R_INTERNAL_ERROR); return -1; } alg_enc = s->psksession->cipher->algorithm_enc; } } else { /* * To get here we must have selected a ciphersuite - otherwise ctx would * be NULL */ if (!ossl_assert(s->s3->tmp.new_cipher != NULL)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, ERR_R_INTERNAL_ERROR); return -1; } alg_enc = s->s3->tmp.new_cipher->algorithm_enc; } if (alg_enc & SSL_AESCCM) { if (alg_enc & (SSL_AES128CCM8 | SSL_AES256CCM8)) taglen = EVP_CCM8_TLS_TAG_LEN; else taglen = EVP_CCM_TLS_TAG_LEN; if (sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, NULL) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, ERR_R_INTERNAL_ERROR); return -1; } } else if (alg_enc & SSL_AESGCM) { taglen = EVP_GCM_TLS_TAG_LEN; } else if (alg_enc & SSL_CHACHA20) { taglen = EVP_CHACHAPOLY_TLS_TAG_LEN; } else { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, ERR_R_INTERNAL_ERROR); return -1; } if (!sending) { /* * Take off tag. There must be at least one byte of content type as * well as the tag */ if (rec->length < taglen + 1) return 0; rec->length -= taglen; } /* Set up IV */ if (ivlen < SEQ_NUM_SIZE) { /* Should not happen */ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, ERR_R_INTERNAL_ERROR); return -1; } offset = ivlen - SEQ_NUM_SIZE; memcpy(iv, staticiv, offset); for (loop = 0; loop < SEQ_NUM_SIZE; loop++) iv[offset + loop] = staticiv[offset + loop] ^ seq[loop]; /* Increment the sequence counter */ for (loop = SEQ_NUM_SIZE; loop > 0; loop--) { ++seq[loop - 1]; if (seq[loop - 1] != 0) break; } if (loop == 0) { /* Sequence has wrapped */ return -1; } /* TODO(size_t): lenu/lenf should be a size_t but EVP doesn't support it */ if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, sending) <= 0 || (!sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, rec->data + rec->length) <= 0)) { return -1; } /* Set up the AAD */ if (!WPACKET_init_static_len(&wpkt, recheader, sizeof(recheader), 0) || !WPACKET_put_bytes_u8(&wpkt, rec->type) || !WPACKET_put_bytes_u16(&wpkt, rec->rec_version) || !WPACKET_put_bytes_u16(&wpkt, rec->length + taglen) || !WPACKET_get_total_written(&wpkt, &hdrlen) || hdrlen != SSL3_RT_HEADER_LENGTH || !WPACKET_finish(&wpkt)) { WPACKET_cleanup(&wpkt); return -1; } /* * For CCM we must explicitly set the total plaintext length before we add * any AAD. */ if (((alg_enc & SSL_AESCCM) != 0 && EVP_CipherUpdate(ctx, NULL, &lenu, NULL, (unsigned int)rec->length) <= 0) || EVP_CipherUpdate(ctx, NULL, &lenu, recheader, sizeof(recheader)) <= 0 || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, (unsigned int)rec->length) <= 0 || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 || (size_t)(lenu + lenf) != rec->length) { return -1; } if (sending) { /* Add the tag */ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen, rec->data + rec->length) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, ERR_R_INTERNAL_ERROR); return -1; } rec->length += taglen; } return 1; }
int AesFileEnc::do_crypt(FILE *in, FILE *out, int do_encrypt) { /* Allow enough space in output buffer for additional block */ unsigned char inbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH]; int inlen, outlen; EVP_CIPHER_CTX ctx; std::cout << "tutaj"; unsigned char* key = this->key(); // std::cout <<key<<std::endl; //unsigned char key[] = "0123456789abcdeF"; std::cout <<key<< std::endl; //unsigned char iv[] = "1234567887654321"; EVP_CIPHER_CTX_init(&ctx); switch(this->type) { case cbc128: EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), NULL, NULL, NULL, do_encrypt); break; case cbc192: EVP_CipherInit_ex(&ctx, EVP_aes_192_cbc(), NULL, NULL, NULL, do_encrypt); break; case cbc256: EVP_CipherInit_ex(&ctx, EVP_aes_256_cbc(), NULL, NULL, NULL, do_encrypt); break; case ecb128: EVP_CipherInit_ex(&ctx, EVP_aes_128_ecb(), NULL, NULL, NULL, do_encrypt); break; case ecb192: EVP_CipherInit_ex(&ctx, EVP_aes_192_ecb(), NULL, NULL, NULL, do_encrypt); break; case ecb256: EVP_CipherInit_ex(&ctx, EVP_aes_256_ecb(), NULL, NULL, NULL, do_encrypt); break; case cfb128: EVP_CipherInit_ex(&ctx, EVP_aes_128_cfb(), NULL, NULL, NULL, do_encrypt); break; case cfb192: EVP_CipherInit_ex(&ctx, EVP_aes_192_cfb(), NULL, NULL, NULL, do_encrypt); break; case cfb256: EVP_CipherInit_ex(&ctx, EVP_aes_256_cfb(), NULL, NULL, NULL, do_encrypt); break; case ofb128: EVP_CipherInit_ex(&ctx, EVP_aes_128_ofb(), NULL, NULL, NULL, do_encrypt); break; case ofb192: EVP_CipherInit_ex(&ctx, EVP_aes_192_ofb(), NULL, NULL, NULL, do_encrypt); break; case ofb256: EVP_CipherInit_ex(&ctx, EVP_aes_256_ofb(), NULL, NULL, NULL, do_encrypt); break; } unsigned char *iv = this->iv(EVP_CIPHER_CTX_iv_length(&ctx)); std::cout<< this->keyLength << std::endl; std::cout<< EVP_CIPHER_CTX_iv_length(&ctx) <<std::endl; OPENSSL_assert(EVP_CIPHER_CTX_key_length(&ctx) == this->keyLength); //OPENSSL_assert(EVP_CIPHER_CTX_iv_length(&ctx) == this->keyLength); EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, do_encrypt); for(;;) { inlen = fread(inbuf, 1, 1024, in); if(inlen <= 0) break; if(!EVP_CipherUpdate(&ctx, outbuf, &outlen, inbuf, inlen)) { EVP_CIPHER_CTX_cleanup(&ctx); return 0; } fwrite(outbuf, 1, outlen, out); } if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen)) { EVP_CIPHER_CTX_cleanup(&ctx); return 0; } fwrite(outbuf, 1, outlen, out); EVP_CIPHER_CTX_cleanup(&ctx); return 1; }
static int sms4_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) { EVP_SMS4_GCM_CTX *gctx = EVP_C_DATA(EVP_SMS4_GCM_CTX,c); switch (type) { case EVP_CTRL_INIT: gctx->key_set = 0; gctx->iv_set = 0; gctx->ivlen = EVP_CIPHER_CTX_iv_length(c); gctx->iv = EVP_CIPHER_CTX_iv_noconst(c); gctx->taglen = -1; gctx->iv_gen = 0; gctx->tls_aad_len = -1; return 1; case EVP_CTRL_AEAD_SET_IVLEN: if (arg <= 0) return 0; /* Allocate memory for IV if needed */ if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen)) { if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(c)) OPENSSL_free(gctx->iv); gctx->iv = OPENSSL_malloc(arg); if (gctx->iv == NULL) return 0; } gctx->ivlen = arg; return 1; case EVP_CTRL_AEAD_SET_TAG: if (arg <= 0 || arg > 16 || EVP_CIPHER_CTX_encrypting(c)) return 0; memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); gctx->taglen = arg; return 1; case EVP_CTRL_AEAD_GET_TAG: if (arg <= 0 || arg > 16 || !EVP_CIPHER_CTX_encrypting(c) || gctx->taglen < 0) return 0; memcpy(ptr, EVP_CIPHER_CTX_buf_noconst(c), arg); return 1; case EVP_CTRL_GCM_SET_IV_FIXED: /* Special case: -1 length restores whole IV */ if (arg == -1) { memcpy(gctx->iv, ptr, gctx->ivlen); gctx->iv_gen = 1; return 1; } /* * Fixed field must be at least 4 bytes and invocation field at least * 8. */ if ((arg < 4) || (gctx->ivlen - arg) < 8) return 0; if (arg) memcpy(gctx->iv, ptr, arg); if (EVP_CIPHER_CTX_encrypting(c) && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0) return 0; gctx->iv_gen = 1; return 1; case EVP_CTRL_GCM_IV_GEN: if (gctx->iv_gen == 0 || gctx->key_set == 0) return 0; CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen); if (arg <= 0 || arg > gctx->ivlen) arg = gctx->ivlen; memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg); /* * Invocation field will be at least 8 bytes in size and so no need * to check wrap around or increment more than last 8 bytes. */ ctr64_inc(gctx->iv + gctx->ivlen - 8); gctx->iv_set = 1; return 1; case EVP_CTRL_GCM_SET_IV_INV: if (gctx->iv_gen == 0 || gctx->key_set == 0 || EVP_CIPHER_CTX_encrypting(c)) return 0; memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg); CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen); gctx->iv_set = 1; return 1; case EVP_CTRL_AEAD_TLS1_AAD: /* Save the AAD for later use */ if (arg != EVP_AEAD_TLS1_AAD_LEN) return 0; memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); gctx->tls_aad_len = arg; { unsigned int len = EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] << 8 | EVP_CIPHER_CTX_buf_noconst(c)[arg - 1]; /* Correct length for explicit IV */ len -= EVP_GCM_TLS_EXPLICIT_IV_LEN; /* If decrypting correct for tag too */ if (!EVP_CIPHER_CTX_encrypting(c)) len -= EVP_GCM_TLS_TAG_LEN; EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] = len >> 8; EVP_CIPHER_CTX_buf_noconst(c)[arg - 1] = len & 0xff; } /* Extra padding: tag appended to record */ return EVP_GCM_TLS_TAG_LEN; case EVP_CTRL_COPY: { EVP_CIPHER_CTX *out = ptr; EVP_SMS4_GCM_CTX *gctx_out = EVP_C_DATA(EVP_SMS4_GCM_CTX,out); if (gctx->gcm.key) { if (gctx->gcm.key != &gctx->ks) return 0; gctx_out->gcm.key = &gctx_out->ks; } if (gctx->iv == EVP_CIPHER_CTX_iv_noconst(c)) gctx_out->iv = EVP_CIPHER_CTX_iv_noconst(out); else { gctx_out->iv = OPENSSL_malloc(gctx->ivlen); if (gctx_out->iv == NULL) return 0; memcpy(gctx_out->iv, gctx->iv, gctx->ivlen); } return 1; } default: return -1; } }
static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) { struct cipher_ctx *cipher_ctx = (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); struct crypt_op cryp; unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); #if !defined(COP_FLAG_WRITE_IV) unsigned char saved_iv[EVP_MAX_IV_LENGTH]; const unsigned char *ivptr; size_t nblocks, ivlen; #endif memset(&cryp, 0, sizeof(cryp)); cryp.ses = cipher_ctx->sess.ses; cryp.len = inl; cryp.src = (void *)in; cryp.dst = (void *)out; cryp.iv = (void *)iv; cryp.op = cipher_ctx->op; #if !defined(COP_FLAG_WRITE_IV) cryp.flags = 0; ivlen = EVP_CIPHER_CTX_iv_length(ctx); if (ivlen > 0) switch (cipher_ctx->mode) { case EVP_CIPH_CBC_MODE: assert(inl >= ivlen); if (!EVP_CIPHER_CTX_encrypting(ctx)) { ivptr = in + inl - ivlen; memcpy(saved_iv, ivptr, ivlen); } break; case EVP_CIPH_CTR_MODE: break; default: /* should not happen */ return 0; } #else cryp.flags = COP_FLAG_WRITE_IV; #endif if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) { SYSerr(SYS_F_IOCTL, errno); return 0; } #if !defined(COP_FLAG_WRITE_IV) if (ivlen > 0) switch (cipher_ctx->mode) { case EVP_CIPH_CBC_MODE: assert(inl >= ivlen); if (EVP_CIPHER_CTX_encrypting(ctx)) ivptr = out + inl - ivlen; else ivptr = saved_iv; memcpy(iv, ivptr, ivlen); break; case EVP_CIPH_CTR_MODE: nblocks = (inl + cipher_ctx->blocksize - 1) / cipher_ctx->blocksize; do { ivlen--; nblocks += iv[ivlen]; iv[ivlen] = (uint8_t) nblocks; nblocks >>= 8; } while (ivlen); break; default: /* should not happen */ return 0; } #endif return 1; }
static int ssl_encrypt_ticket_with_cipher_ctx(SSL *ssl, CBB *out, const uint8_t *session_buf, size_t session_len) { int ret = 0; EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); HMAC_CTX hctx; HMAC_CTX_init(&hctx); /* If the session is too long, emit a dummy value rather than abort the * connection. */ static const size_t kMaxTicketOverhead = 16 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE; if (session_len > 0xffff - kMaxTicketOverhead) { static const char kTicketPlaceholder[] = "TICKET TOO LARGE"; if (CBB_add_bytes(out, (const uint8_t *)kTicketPlaceholder, strlen(kTicketPlaceholder))) { ret = 1; } goto err; } /* Initialize HMAC and cipher contexts. If callback present it does all the * work otherwise use generated values from parent ctx. */ SSL_CTX *tctx = ssl->session_ctx; uint8_t iv[EVP_MAX_IV_LENGTH]; uint8_t key_name[16]; if (tctx->tlsext_ticket_key_cb != NULL) { if (tctx->tlsext_ticket_key_cb(ssl, key_name, iv, &ctx, &hctx, 1 /* encrypt */) < 0) { goto err; } } else { if (!RAND_bytes(iv, 16) || !EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, tctx->tlsext_tick_aes_key, iv) || !HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(), NULL)) { goto err; } OPENSSL_memcpy(key_name, tctx->tlsext_tick_key_name, 16); } uint8_t *ptr; if (!CBB_add_bytes(out, key_name, 16) || !CBB_add_bytes(out, iv, EVP_CIPHER_CTX_iv_length(&ctx)) || !CBB_reserve(out, &ptr, session_len + EVP_MAX_BLOCK_LENGTH)) { goto err; } size_t total = 0; #if defined(BORINGSSL_UNSAFE_FUZZER_MODE) OPENSSL_memcpy(ptr, session_buf, session_len); total = session_len; #else int len; if (!EVP_EncryptUpdate(&ctx, ptr + total, &len, session_buf, session_len)) { goto err; } total += len; if (!EVP_EncryptFinal_ex(&ctx, ptr + total, &len)) { goto err; } total += len; #endif if (!CBB_did_write(out, total)) { goto err; } unsigned hlen; if (!HMAC_Update(&hctx, CBB_data(out), CBB_len(out)) || !CBB_reserve(out, &ptr, EVP_MAX_MD_SIZE) || !HMAC_Final(&hctx, ptr, &hlen) || !CBB_did_write(out, hlen)) { goto err; } ret = 1; err: EVP_CIPHER_CTX_cleanup(&ctx); HMAC_CTX_cleanup(&hctx); return ret; }
int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc) { if (enc == -1) enc = ctx->encrypt; else { if (enc) enc = 1; ctx->encrypt = enc; } #ifdef OPENSSL_NO_FIPS if(FIPS_selftest_failed()) { FIPSerr(FIPS_F_EVP_CIPHERINIT_EX,FIPS_R_FIPS_SELFTEST_FAILED); ctx->cipher = &bad_cipher; return 0; } #endif #ifndef OPENSSL_NO_ENGINE /* Whether it's nice or not, "Inits" can be used on "Final"'d contexts * so this context may already have an ENGINE! Try to avoid releasing * the previous handle, re-querying for an ENGINE, and having a * reinitialisation, when it may all be unecessary. */ if (ctx->engine && ctx->cipher && (!cipher || (cipher && (cipher->nid == ctx->cipher->nid)))) goto skip_to_init; #endif if (cipher) { /* Ensure a context left lying around from last time is cleared * (the previous check attempted to avoid this if the same * ENGINE and EVP_CIPHER could be used). */ EVP_CIPHER_CTX_cleanup(ctx); /* Restore encrypt field: it is zeroed by cleanup */ ctx->encrypt = enc; #ifndef OPENSSL_NO_ENGINE if (!do_evp_enc_engine(ctx, &cipher, impl)) return 0; #endif ctx->cipher=cipher; if (ctx->cipher->ctx_size) { ctx->cipher_data=OPENSSL_malloc(ctx->cipher->ctx_size); if (!ctx->cipher_data) { EVPerr(EVP_F_EVP_CIPHERINIT_EX, ERR_R_MALLOC_FAILURE); return 0; } } else { ctx->cipher_data = NULL; } ctx->key_len = cipher->key_len; ctx->flags = 0; if(ctx->cipher->flags & EVP_CIPH_CTRL_INIT) { if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) { EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); return 0; } } } else if(!ctx->cipher) { EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_NO_CIPHER_SET); return 0; } #ifndef OPENSSL_NO_ENGINE skip_to_init: #endif /* we assume block size is a power of 2 in *cryptUpdate */ OPENSSL_assert(ctx->cipher->block_size == 1 || ctx->cipher->block_size == 8 || ctx->cipher->block_size == 16); if(!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) { switch(EVP_CIPHER_CTX_mode(ctx)) { case EVP_CIPH_STREAM_CIPHER: case EVP_CIPH_ECB_MODE: break; case EVP_CIPH_CFB_MODE: case EVP_CIPH_OFB_MODE: ctx->num = 0; case EVP_CIPH_CBC_MODE: OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) <= (int)sizeof(ctx->iv)); if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); break; default: return 0; break; } } #ifdef OPENSSL_FIPS /* After 'key' is set no further parameters changes are permissible. * So only check for non FIPS enabling at this point. */ if (key && FIPS_mode()) { if (!(ctx->cipher->flags & EVP_CIPH_FLAG_FIPS) & !(ctx->flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW)) { EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_DISABLED_FOR_FIPS); #if 0 ERR_add_error_data(2, "cipher=", EVP_CIPHER_name(ctx->cipher)); #endif ctx->cipher = &bad_cipher; return 0; } } #endif if(key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) { if(!ctx->cipher->init(ctx,key,iv,enc)) return 0; } ctx->buf_len=0; ctx->final_used=0; ctx->block_mask=ctx->cipher->block_size-1; return 1; }
CMS_RecipientInfo * CMS_add0_recipient_password(CMS_ContentInfo *cms, int iter, int wrap_nid, int pbe_nid, unsigned char *pass, ssize_t passlen, const EVP_CIPHER *kekciph) { CMS_RecipientInfo *ri = NULL; CMS_EnvelopedData *env; CMS_PasswordRecipientInfo *pwri; EVP_CIPHER_CTX ctx; X509_ALGOR *encalg = NULL; unsigned char iv[EVP_MAX_IV_LENGTH]; int ivlen; env = cms_get0_enveloped(cms); if (!env) return NULL; if (wrap_nid <= 0) wrap_nid = NID_id_alg_PWRI_KEK; if (pbe_nid <= 0) pbe_nid = NID_id_pbkdf2; /* Get from enveloped data */ if (kekciph == NULL) kekciph = env->encryptedContentInfo->cipher; if (kekciph == NULL) { CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_NO_CIPHER); return NULL; } if (wrap_nid != NID_id_alg_PWRI_KEK) { CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); return NULL; } /* Setup algorithm identifier for cipher */ encalg = X509_ALGOR_new(); EVP_CIPHER_CTX_init(&ctx); if (EVP_EncryptInit_ex(&ctx, kekciph, NULL, NULL, NULL) <= 0) { CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB); goto err; } ivlen = EVP_CIPHER_CTX_iv_length(&ctx); if (ivlen > 0) { arc4random_buf(iv, ivlen); if (EVP_EncryptInit_ex(&ctx, NULL, NULL, NULL, iv) <= 0) { CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB); goto err; } encalg->parameter = ASN1_TYPE_new(); if (!encalg->parameter) { CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE); goto err; } if (EVP_CIPHER_param_to_asn1(&ctx, encalg->parameter) <= 0) { CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); goto err; } } encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(&ctx)); EVP_CIPHER_CTX_cleanup(&ctx); /* Initialize recipient info */ ri = M_ASN1_new_of(CMS_RecipientInfo); if (!ri) goto merr; ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo); if (!ri->d.pwri) goto merr; ri->type = CMS_RECIPINFO_PASS; pwri = ri->d.pwri; /* Since this is overwritten, free up empty structure already there */ X509_ALGOR_free(pwri->keyEncryptionAlgorithm); pwri->keyEncryptionAlgorithm = X509_ALGOR_new(); if (!pwri->keyEncryptionAlgorithm) goto merr; pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid); pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new(); if (!pwri->keyEncryptionAlgorithm->parameter) goto merr; if (!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR), &pwri->keyEncryptionAlgorithm->parameter->value.sequence)) goto merr; pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE; X509_ALGOR_free(encalg); encalg = NULL; /* Setup PBE algorithm */ pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1); if (!pwri->keyDerivationAlgorithm) goto err; CMS_RecipientInfo_set0_password(ri, pass, passlen); pwri->version = 0; if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) goto merr; return ri; merr: CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE); err: EVP_CIPHER_CTX_cleanup(&ctx); if (ri) M_ASN1_free_of(ri, CMS_RecipientInfo); if (encalg) X509_ALGOR_free(encalg); return NULL; }
/** Encrypt some data. * \param key_count Number of keys in the \a target array. * \param target Array of keys. Anyone who owns any of these keys will be * able to decrypt the data. These keys must include public key data. * \param data Group to encrypt. Will be replaced by an encrypted group. * \return Nonzero iff the operation succeeded. * \sa gale_crypto_target(), gale_crypto_open() */ int gale_crypto_seal( int key_count,const struct gale_group *target, struct gale_group *data) { struct gale_fragment frag; struct gale_data plain,cipher; EVP_CIPHER_CTX *context = EVP_CIPHER_CTX_new(); int i,*session_key_length; unsigned char **session_key,iv[EVP_MAX_IV_LENGTH]; struct gale_text *raw_name; EVP_PKEY **public_key; RSA *rsa; int good_count = 0,is_successful = 0; plain.p = gale_malloc(gale_group_size(*data) + gale_u32_size()); plain.l = 0; gale_pack_u32(&plain,0); /* version identifier? */ gale_pack_group(&plain,*data); *data = gale_group_empty(); gale_create_array(raw_name,key_count); gale_create_array(public_key,key_count); for (i = 0; i < key_count; ++i) public_key[i] = NULL; for (i = 0; i < key_count; ++i) { public_key[good_count] = EVP_PKEY_new(); EVP_PKEY_assign_RSA(public_key[good_count],RSA_new()); rsa = EVP_PKEY_get0_RSA(public_key[good_count]); raw_name[good_count] = key_i_swizzle(crypto_i_rsa( target[i],rsa)); if (0 != raw_name[good_count].l && crypto_i_public_valid(rsa)) ++good_count; else EVP_PKEY_free(public_key[good_count]); } gale_create_array(session_key_length,good_count); gale_create_array(session_key,good_count); for (i = 0; i < good_count; ++i) gale_create_array(session_key[i],EVP_PKEY_size(public_key[i])); crypto_i_seed(); if (!EVP_SealInit(context,EVP_des_ede3_cbc(), session_key,session_key_length,iv,public_key,good_count)) { crypto_i_error(); goto cleanup; } cipher.l = gale_copy_size(sizeof(magic2)) + gale_copy_size(EVP_CIPHER_CTX_iv_length(context)) + gale_u32_size() + plain.l + EVP_CIPHER_CTX_block_size(context) - 1; for (i = 0; i < good_count; ++i) cipher.l += gale_text_size(raw_name[i]) + gale_u32_size() + gale_copy_size(session_key_length[i]); cipher.p = gale_malloc(cipher.l); cipher.l = 0; assert(IV_LEN == EVP_CIPHER_CTX_iv_length(context)); gale_pack_copy(&cipher,magic2,sizeof(magic2)); gale_pack_copy(&cipher,iv,IV_LEN); gale_pack_u32(&cipher,good_count); for (i = 0; i < good_count; ++i) { gale_pack_text(&cipher,raw_name[i]); gale_pack_u32(&cipher,session_key_length[i]); gale_pack_copy(&cipher,session_key[i],session_key_length[i]); } EVP_SealUpdate(context,cipher.p + cipher.l,&i,plain.p,plain.l); cipher.l += i; EVP_SealFinal(context,cipher.p + cipher.l,&i); cipher.l += i; frag.type = frag_data; frag.name = G_("security/encryption"); frag.value.data = cipher; gale_group_add(data,frag); is_successful = 1; cleanup: for (i = 0; i < good_count; ++i) if (NULL != public_key[i]) EVP_PKEY_free(public_key[i]); return is_successful; }