summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--engines/e_ossltest.c216
-rw-r--r--ssl/record/ssl3_record.c23
-rw-r--r--ssl/record/tls_pad.c2
-rw-r--r--ssl/tls_depr.c10
4 files changed, 210 insertions, 41 deletions
diff --git a/engines/e_ossltest.c b/engines/e_ossltest.c
index 8479414f01..0506faa628 100644
--- a/engines/e_ossltest.c
+++ b/engines/e_ossltest.c
@@ -38,6 +38,7 @@
#include <openssl/rand.h>
#include <openssl/crypto.h>
#include <openssl/pem.h>
+#include <crypto/evp.h>
#include "e_ossltest_err.c"
@@ -247,21 +248,39 @@ static int ossltest_ciphers(ENGINE *, const EVP_CIPHER **,
const int **, int);
static int ossltest_cipher_nids[] = {
- NID_aes_128_cbc, NID_aes_128_gcm, 0
+ NID_aes_128_cbc, NID_aes_128_gcm,
+ NID_aes_128_cbc_hmac_sha1, 0
};
/* AES128 */
-int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
- const unsigned char *iv, int enc);
-int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl);
-int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
- const unsigned char *iv, int enc);
-int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl);
+static int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx,
+ const unsigned char *key,
+ const unsigned char *iv, int enc);
+static int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl);
+static int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx,
+ const unsigned char *key,
+ const unsigned char *iv, int enc);
+static int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl);
static int ossltest_aes128_gcm_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
void *ptr);
+static int ossltest_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx,
+ const unsigned char *key,
+ const unsigned char *iv,
+ int enc);
+static int ossltest_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx,
+ unsigned char *out,
+ const unsigned char *in,
+ size_t inl);
+static int ossltest_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type,
+ int arg, void *ptr);
+
+typedef struct {
+ size_t payload_length; /* AAD length in decrypt case */
+ unsigned int tls_ver;
+} EVP_AES_HMAC_SHA1;
static EVP_CIPHER *_hidden_aes_128_cbc = NULL;
static const EVP_CIPHER *ossltest_aes_128_cbc(void)
@@ -285,6 +304,7 @@ static const EVP_CIPHER *ossltest_aes_128_cbc(void)
}
return _hidden_aes_128_cbc;
}
+
static EVP_CIPHER *_hidden_aes_128_gcm = NULL;
#define AES_GCM_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \
@@ -315,11 +335,45 @@ static const EVP_CIPHER *ossltest_aes_128_gcm(void)
return _hidden_aes_128_gcm;
}
+static EVP_CIPHER *_hidden_aes_128_cbc_hmac_sha1 = NULL;
+
+static const EVP_CIPHER *ossltest_aes_128_cbc_hmac_sha1(void)
+{
+ if (_hidden_aes_128_cbc_hmac_sha1 == NULL
+ && ((_hidden_aes_128_cbc_hmac_sha1
+ = EVP_CIPHER_meth_new(NID_aes_128_cbc_hmac_sha1,
+ 16 /* block size */,
+ 16 /* key len */)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_cbc_hmac_sha1,16)
+ || !EVP_CIPHER_meth_set_flags(_hidden_aes_128_cbc_hmac_sha1,
+ EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 |
+ EVP_CIPH_FLAG_AEAD_CIPHER)
+ || !EVP_CIPHER_meth_set_init(_hidden_aes_128_cbc_hmac_sha1,
+ ossltest_aes128_cbc_hmac_sha1_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_cbc_hmac_sha1,
+ ossltest_aes128_cbc_hmac_sha1_cipher)
+ || !EVP_CIPHER_meth_set_ctrl(_hidden_aes_128_cbc_hmac_sha1,
+ ossltest_aes128_cbc_hmac_sha1_ctrl)
+ || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_aes_128_cbc_hmac_sha1,
+ EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv)
+ || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_aes_128_cbc_hmac_sha1,
+ EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_cbc_hmac_sha1,
+ sizeof(EVP_AES_HMAC_SHA1)))) {
+ EVP_CIPHER_meth_free(_hidden_aes_128_cbc_hmac_sha1);
+ _hidden_aes_128_cbc_hmac_sha1 = NULL;
+ }
+ return _hidden_aes_128_cbc_hmac_sha1;
+}
+
static void destroy_ciphers(void)
{
EVP_CIPHER_meth_free(_hidden_aes_128_cbc);
EVP_CIPHER_meth_free(_hidden_aes_128_gcm);
+ EVP_CIPHER_meth_free(_hidden_aes_128_cbc_hmac_sha1);
_hidden_aes_128_cbc = NULL;
+ _hidden_aes_128_gcm = NULL;
+ _hidden_aes_128_cbc_hmac_sha1 = NULL;
}
/* Key loading */
@@ -490,6 +544,9 @@ static int ossltest_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
case NID_aes_128_gcm:
*cipher = ossltest_aes_128_gcm();
break;
+ case NID_aes_128_cbc_hmac_sha1:
+ *cipher = ossltest_aes_128_cbc_hmac_sha1();
+ break;
default:
ok = 0;
*cipher = NULL;
@@ -634,14 +691,15 @@ static int digest_sha512_final(EVP_MD_CTX *ctx, unsigned char *md)
* AES128 Implementation
*/
-int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
- const unsigned char *iv, int enc)
+static int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx,
+ const unsigned char *key,
+ const unsigned char *iv, int enc)
{
return EVP_CIPHER_meth_get_init(EVP_aes_128_cbc()) (ctx, key, iv, enc);
}
-int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
+static int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
{
unsigned char *tmpbuf;
int ret;
@@ -667,15 +725,15 @@ int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return ret;
}
-int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
- const unsigned char *iv, int enc)
+static int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx,
+ const unsigned char *key,
+ const unsigned char *iv, int enc)
{
return EVP_CIPHER_meth_get_init(EVP_aes_128_gcm()) (ctx, key, iv, enc);
}
-
-int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
+static int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
{
unsigned char *tmpbuf = OPENSSL_malloc(inl);
@@ -720,6 +778,128 @@ static int ossltest_aes128_gcm_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
return 1;
}
+#define NO_PAYLOAD_LENGTH ((size_t)-1)
+# define data(ctx) ((EVP_AES_HMAC_SHA1 *)EVP_CIPHER_CTX_get_cipher_data(ctx))
+
+static int ossltest_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx,
+ const unsigned char *inkey,
+ const unsigned char *iv,
+ int enc)
+{
+ EVP_AES_HMAC_SHA1 *key = data(ctx);
+ key->payload_length = NO_PAYLOAD_LENGTH;
+ return 1;
+}
+
+static int ossltest_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx,
+ unsigned char *out,
+ const unsigned char *in,
+ size_t len)
+{
+ EVP_AES_HMAC_SHA1 *key = data(ctx);
+ unsigned int l;
+ size_t plen = key->payload_length;
+
+ key->payload_length = NO_PAYLOAD_LENGTH;
+
+ if (len % AES_BLOCK_SIZE)
+ return 0;
+
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
+ if (plen == NO_PAYLOAD_LENGTH)
+ plen = len;
+ else if (len !=
+ ((plen + SHA_DIGEST_LENGTH +
+ AES_BLOCK_SIZE) & -AES_BLOCK_SIZE))
+ return 0;
+
+ memmove(out, in, plen);
+
+ if (plen != len) { /* "TLS" mode of operation */
+ /* calculate HMAC and append it to payload */
+ fill_known_data(out + plen, SHA_DIGEST_LENGTH);
+
+ /* pad the payload|hmac */
+ plen += SHA_DIGEST_LENGTH;
+ for (l = len - plen - 1; plen < len; plen++)
+ out[plen] = l;
+ }
+ } else {
+ /* decrypt HMAC|padding at once */
+ memmove(out, in, len);
+
+ if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */
+ unsigned int maxpad, pad;
+
+ if (key->tls_ver >= TLS1_1_VERSION) {
+ if (len < (AES_BLOCK_SIZE + SHA_DIGEST_LENGTH + 1))
+ return 0;
+
+ /* omit explicit iv */
+ in += AES_BLOCK_SIZE;
+ out += AES_BLOCK_SIZE;
+ len -= AES_BLOCK_SIZE;
+ } else if (len < (SHA_DIGEST_LENGTH + 1))
+ return 0;
+
+ /* figure out payload length */
+ pad = out[len - 1];
+ maxpad = len - (SHA_DIGEST_LENGTH + 1);
+ if (pad > maxpad)
+ return 0;
+ for (plen = len - pad - 1; plen < len; plen++)
+ if (out[plen] != pad)
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int ossltest_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type,
+ int arg, void *ptr)
+{
+ EVP_AES_HMAC_SHA1 *key = data(ctx);
+
+ switch (type) {
+ case EVP_CTRL_AEAD_SET_MAC_KEY:
+ return 1;
+
+ case EVP_CTRL_AEAD_TLS1_AAD:
+ {
+ unsigned char *p = ptr;
+ unsigned int len;
+
+ if (arg != EVP_AEAD_TLS1_AAD_LEN)
+ return -1;
+
+ len = p[arg - 2] << 8 | p[arg - 1];
+ key->tls_ver = p[arg - 4] << 8 | p[arg - 3];
+
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
+ key->payload_length = len;
+ if (key->tls_ver >= TLS1_1_VERSION) {
+ if (len < AES_BLOCK_SIZE)
+ return 0;
+ len -= AES_BLOCK_SIZE;
+ p[arg - 2] = len >> 8;
+ p[arg - 1] = len;
+ }
+
+ return (int)(((len + SHA_DIGEST_LENGTH +
+ AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)
+ - len);
+ } else {
+ key->payload_length = arg;
+
+ return SHA_DIGEST_LENGTH;
+ }
+ }
+ default:
+ return -1;
+ }
+}
+
static int ossltest_rand_bytes(unsigned char *buf, int num)
{
unsigned char val = 1;
diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c
index b6ac61e0e8..c713f231ca 100644
--- a/ssl/record/ssl3_record.c
+++ b/ssl/record/ssl3_record.c
@@ -1218,23 +1218,17 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending,
}
if (!sending) {
- /* Adjust the record to remove the explicit IV/MAC/Tag */
- if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_GCM_MODE) {
- for (ctr = 0; ctr < n_recs; ctr++) {
+ for (ctr = 0; ctr < n_recs; ctr++) {
+ /* Adjust the record to remove the explicit IV/MAC/Tag */
+ if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_GCM_MODE) {
recs[ctr].data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
recs[ctr].input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
recs[ctr].length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
- }
- } else if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_CCM_MODE) {
- for (ctr = 0; ctr < n_recs; ctr++) {
+ } else if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_CCM_MODE) {
recs[ctr].data += EVP_CCM_TLS_EXPLICIT_IV_LEN;
recs[ctr].input += EVP_CCM_TLS_EXPLICIT_IV_LEN;
recs[ctr].length -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
- }
- }
-
- for (ctr = 0; ctr < n_recs; ctr++) {
- if (bs != 1 && SSL_USE_EXPLICIT_IV(s)) {
+ } else if (bs != 1 && SSL_USE_EXPLICIT_IV(s)) {
if (recs[ctr].length < bs)
return 0;
recs[ctr].data += bs;
@@ -1254,17 +1248,12 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending,
(macs != NULL) ? &macs[ctr].alloced
: NULL,
bs,
- macsize,
+ pad ? (size_t)pad : macsize,
(EVP_CIPHER_get_flags(enc)
& EVP_CIPH_FLAG_AEAD_CIPHER) != 0,
s->ctx->libctx))
return 0;
}
- if (pad) {
- for (ctr = 0; ctr < n_recs; ctr++) {
- recs[ctr].length -= pad;
- }
- }
}
}
}
diff --git a/ssl/record/tls_pad.c b/ssl/record/tls_pad.c
index 46614e143b..528c605554 100644
--- a/ssl/record/tls_pad.c
+++ b/ssl/record/tls_pad.c
@@ -138,8 +138,6 @@ int tls1_cbc_remove_padding_and_mac(size_t *reclen,
if (aead) {
/* padding is already verified and we don't need to check the MAC */
*reclen -= padding_length + 1 + mac_size;
- *mac = NULL;
- *alloced = 0;
return 1;
}
diff --git a/ssl/tls_depr.c b/ssl/tls_depr.c
index 0b21ff7669..1761ba1d8e 100644
--- a/ssl/tls_depr.c
+++ b/ssl/tls_depr.c
@@ -27,6 +27,7 @@ void tls_engine_finish(ENGINE *e)
const EVP_CIPHER *tls_get_cipher_from_engine(int nid)
{
+ const EVP_CIPHER *ret = NULL;
#ifndef OPENSSL_NO_ENGINE
ENGINE *eng;
@@ -36,15 +37,16 @@ const EVP_CIPHER *tls_get_cipher_from_engine(int nid)
*/
eng = ENGINE_get_cipher_engine(nid);
if (eng != NULL) {
+ ret = ENGINE_get_cipher(eng, nid);
ENGINE_finish(eng);
- return EVP_get_cipherbynid(nid);
}
#endif
- return NULL;
+ return ret;
}
const EVP_MD *tls_get_digest_from_engine(int nid)
{
+ const EVP_MD *ret = NULL;
#ifndef OPENSSL_NO_ENGINE
ENGINE *eng;
@@ -54,11 +56,11 @@ const EVP_MD *tls_get_digest_from_engine(int nid)
*/
eng = ENGINE_get_digest_engine(nid);
if (eng != NULL) {
+ ret = ENGINE_get_digest(eng, nid);
ENGINE_finish(eng);
- return EVP_get_digestbynid(nid);
}
#endif
- return NULL;
+ return ret;
}
#ifndef OPENSSL_NO_ENGINE