Add AES KW inverse ciphers to the EVP layer
[openssl.git] / providers / implementations / ciphers / cipher_aes_wrp.c
index 0de2a5f651f1f7b5d2451e5aaf9a817a00ea860e..ca57666e7ab7a60d18d0c32e105672f745ba5429 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -14,6 +14,7 @@
 #include "internal/deprecated.h"
 
 #include "cipher_aes.h"
+#include "prov/providercommon.h"
 #include "prov/providercommonerr.h"
 #include "prov/implementations.h"
 
 /* TODO(3.0) Figure out what flags need to be passed */
 #define WRAP_FLAGS (EVP_CIPH_WRAP_MODE | EVP_CIPH_CUSTOM_IV \
                     | EVP_CIPH_ALWAYS_CALL_INIT)
+#define WRAP_FLAGS_INV (WRAP_FLAGS | EVP_CIPH_FLAG_INVERSE_CIPHER)
 
 typedef size_t (*aeswrap_fn)(void *key, const unsigned char *iv,
                              unsigned char *out, const unsigned char *in,
                              size_t inlen, block128_f block);
 
-static OSSL_OP_cipher_encrypt_init_fn aes_wrap_einit;
-static OSSL_OP_cipher_decrypt_init_fn aes_wrap_dinit;
-static OSSL_OP_cipher_update_fn aes_wrap_cipher;
-static OSSL_OP_cipher_final_fn aes_wrap_final;
-static OSSL_OP_cipher_freectx_fn aes_wrap_freectx;
+static OSSL_FUNC_cipher_encrypt_init_fn aes_wrap_einit;
+static OSSL_FUNC_cipher_decrypt_init_fn aes_wrap_dinit;
+static OSSL_FUNC_cipher_update_fn aes_wrap_cipher;
+static OSSL_FUNC_cipher_final_fn aes_wrap_final;
+static OSSL_FUNC_cipher_freectx_fn aes_wrap_freectx;
 
 typedef struct prov_aes_wrap_ctx_st {
     PROV_CIPHER_CTX base;
@@ -49,12 +51,17 @@ typedef struct prov_aes_wrap_ctx_st {
 static void *aes_wrap_newctx(size_t kbits, size_t blkbits,
                              size_t ivbits, unsigned int mode, uint64_t flags)
 {
-    PROV_AES_WRAP_CTX *wctx = OPENSSL_zalloc(sizeof(*wctx));
-    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)wctx;
+    PROV_AES_WRAP_CTX *wctx;
+    PROV_CIPHER_CTX *ctx;
 
+    if (!ossl_prov_is_running())
+        return NULL;
+
+    wctx = OPENSSL_zalloc(sizeof(*wctx));
+    ctx = (PROV_CIPHER_CTX *)wctx;
     if (ctx != NULL) {
-        cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags,
-                               NULL, NULL);
+        ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags,
+                                    NULL, NULL);
         ctx->pad = (ctx->ivlen == AES_WRAP_PAD_IVLEN);
     }
     return wctx;
@@ -64,6 +71,7 @@ static void aes_wrap_freectx(void *vctx)
 {
     PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
 
+    ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
     OPENSSL_clear_free(wctx,  sizeof(*wctx));
 }
 
@@ -74,26 +82,46 @@ static int aes_wrap_init(void *vctx, const unsigned char *key,
     PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
     PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
 
+    if (!ossl_prov_is_running())
+        return 0;
+
     ctx->enc = enc;
-    ctx->block = enc ? (block128_f)AES_encrypt : (block128_f)AES_decrypt;
     if (ctx->pad)
         wctx->wrapfn = enc ? CRYPTO_128_wrap_pad : CRYPTO_128_unwrap_pad;
     else
         wctx->wrapfn = enc ? CRYPTO_128_wrap : CRYPTO_128_unwrap;
 
     if (iv != NULL) {
-        if (!cipher_generic_initiv(ctx, iv, ivlen))
+        if (!ossl_cipher_generic_initiv(ctx, iv, ivlen))
             return 0;
     }
     if (key != NULL) {
+        int use_forward_transform;
+
         if (keylen != ctx->keylen) {
            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
            return 0;
         }
-        if (ctx->enc)
-            AES_set_encrypt_key(key, keylen * 8, &wctx->ks.ks);
+        /*
+         * See SP800-38F : Section 5.1
+         * The forward and inverse transformations for the AES block
+         * cipher—called “cipher” and “inverse  cipher” are informally known as
+         * the AES encryption and AES decryption functions, respectively.
+         * If the designated cipher function for a key-wrap algorithm is chosen
+         * to be the AES decryption function, then CIPH-1K will be the AES
+         * encryption function.
+         */
+        if ((ctx->flags & EVP_CIPH_FLAG_INVERSE_CIPHER) == 0)
+            use_forward_transform = ctx->enc;
         else
+            use_forward_transform = !ctx->enc;
+        if (use_forward_transform) {
+            AES_set_encrypt_key(key, keylen * 8, &wctx->ks.ks);
+            ctx->block = (block128_f)AES_encrypt;
+        } else {
             AES_set_decrypt_key(key, keylen * 8, &wctx->ks.ks);
+            ctx->block = (block128_f)AES_decrypt;
+        }
     }
     return 1;
 }
@@ -159,6 +187,9 @@ static int aes_wrap_cipher_internal(void *vctx, unsigned char *out,
 static int aes_wrap_final(void *vctx, unsigned char *out, size_t *outl,
                           size_t outsize)
 {
+    if (!ossl_prov_is_running())
+        return 0;
+
     *outl = 0;
     return 1;
 }
@@ -170,6 +201,9 @@ static int aes_wrap_cipher(void *vctx,
     PROV_AES_WRAP_CTX *ctx = (PROV_AES_WRAP_CTX *)vctx;
     size_t len;
 
+    if (!ossl_prov_is_running())
+        return 0;
+
     if (inl == 0) {
         *outl = 0;
         return 1;
@@ -209,19 +243,19 @@ static int aes_wrap_set_ctx_params(void *vctx, const OSSL_PARAM params[])
 }
 
 #define IMPLEMENT_cipher(mode, fname, UCMODE, flags, kbits, blkbits, ivbits)   \
-    static OSSL_OP_cipher_get_params_fn aes_##kbits##_##fname##_get_params;    \
+    static OSSL_FUNC_cipher_get_params_fn aes_##kbits##_##fname##_get_params;  \
     static int aes_##kbits##_##fname##_get_params(OSSL_PARAM params[])         \
     {                                                                          \
-        return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,     \
-                                         flags, kbits, blkbits, ivbits);       \
+        return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,\
+                                              flags, kbits, blkbits, ivbits);  \
     }                                                                          \
-    static OSSL_OP_cipher_newctx_fn aes_##kbits##fname##_newctx;               \
+    static OSSL_FUNC_cipher_newctx_fn aes_##kbits##fname##_newctx;             \
     static void *aes_##kbits##fname##_newctx(void *provctx)                    \
     {                                                                          \
         return aes_##mode##_newctx(kbits, blkbits, ivbits,                     \
                                    EVP_CIPH_##UCMODE##_MODE, flags);           \
     }                                                                          \
-    const OSSL_DISPATCH aes##kbits##fname##_functions[] = {                    \
+    const OSSL_DISPATCH ossl_##aes##kbits##fname##_functions[] = {             \
         { OSSL_FUNC_CIPHER_NEWCTX,                                             \
             (void (*)(void))aes_##kbits##fname##_newctx },                     \
         { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_##mode##_einit }, \
@@ -232,15 +266,15 @@ static int aes_wrap_set_ctx_params(void *vctx, const OSSL_PARAM params[])
         { OSSL_FUNC_CIPHER_GET_PARAMS,                                         \
             (void (*)(void))aes_##kbits##_##fname##_get_params },              \
         { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,                                    \
-            (void (*)(void))cipher_generic_gettable_params },                  \
+            (void (*)(void))ossl_cipher_generic_gettable_params },             \
         { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,                                     \
-            (void (*)(void))cipher_generic_get_ctx_params },                   \
+            (void (*)(void))ossl_cipher_generic_get_ctx_params },              \
         { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,                                     \
             (void (*)(void))aes_wrap_set_ctx_params },                         \
         { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,                                \
-            (void (*)(void))cipher_generic_gettable_ctx_params },              \
+            (void (*)(void))ossl_cipher_generic_gettable_ctx_params },         \
         { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,                                \
-            (void (*)(void))cipher_generic_settable_ctx_params },              \
+            (void (*)(void))ossl_cipher_generic_settable_ctx_params },         \
         { 0, NULL }                                                            \
     }
 
@@ -250,3 +284,10 @@ IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_NOPAD_IVLEN * 8
 IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_PAD_IVLEN * 8);
 IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_PAD_IVLEN * 8);
 IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_PAD_IVLEN * 8);
+
+IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 256, 64, AES_WRAP_NOPAD_IVLEN * 8);
+IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 192, 64, AES_WRAP_NOPAD_IVLEN * 8);
+IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 128, 64, AES_WRAP_NOPAD_IVLEN * 8);
+IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 256, 64, AES_WRAP_PAD_IVLEN * 8);
+IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 192, 64, AES_WRAP_PAD_IVLEN * 8);
+IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 128, 64, AES_WRAP_PAD_IVLEN * 8);