Fix copy for CCM, GCM and XTS.
authorDr. Stephen Henson <steve@openssl.org>
Mon, 30 Jun 2014 11:57:29 +0000 (12:57 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 30 Jun 2014 13:00:00 +0000 (14:00 +0100)
Internal pointers in CCM, GCM and XTS contexts should either be
NULL or set to point to the appropriate key schedule. This needs
to be adjusted when copying contexts.
(cherry picked from commit c2fd5d79ffc4fc9d120a0faad579ce96473e6a2f)

crypto/evp/e_aes.c

index d11588cf36001aee4c896e1bff92aa1e725c7940..07bf83a608d87a14a1b2b3826e9cac7388e91d6f 100644 (file)
@@ -812,6 +812,12 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
                {
                        EVP_CIPHER_CTX *out = ptr;
                        EVP_AES_GCM_CTX *gctx_out = out->cipher_data;
+                       if (gctx->gcm.key)
+                               {
+                               if (gctx->gcm.key != &gctx->ks)
+                                       return 0;
+                               gctx_out->gcm.key = &gctx_out->ks;
+                               }
                        if (gctx->iv == c->iv)
                                gctx_out->iv = out->iv;
                        else
@@ -1061,7 +1067,25 @@ BLOCK_CIPHER_custom(NID_aes,256,1,12,gcm,GCM,
 static int aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
        {
        EVP_AES_XTS_CTX *xctx = c->cipher_data;
-       if (type != EVP_CTRL_INIT)
+       if (type == EVP_CTRL_COPY)
+               {
+               EVP_CIPHER_CTX *out = ptr;
+               EVP_AES_XTS_CTX *xctx_out = out->cipher_data;
+               if (xctx->xts.key1)
+                       {
+                       if (xctx->xts.key1 != &xctx->ks1)
+                               return 0;
+                       xctx_out->xts.key1 = &xctx_out->ks1;
+                       }
+               if (xctx->xts.key2)
+                       {
+                       if (xctx->xts.key2 != &xctx->ks2)
+                               return 0;
+                       xctx_out->xts.key2 = &xctx_out->ks2;
+                       }
+               return 1;
+               }
+       else if (type != EVP_CTRL_INIT)
                return -1;
        /* key1 and key2 are used as an indicator both key and IV are set */
        xctx->xts.key1 = NULL;
@@ -1170,7 +1194,8 @@ static int aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
 #define aes_xts_cleanup NULL
 
 #define XTS_FLAGS      (EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV \
-                        | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT)
+                        | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
+                        | EVP_CIPH_CUSTOM_COPY)
 
 BLOCK_CIPHER_custom(NID_aes,128,1,16,xts,XTS,EVP_CIPH_FLAG_FIPS|XTS_FLAGS)
 BLOCK_CIPHER_custom(NID_aes,256,1,16,xts,XTS,EVP_CIPH_FLAG_FIPS|XTS_FLAGS)
@@ -1220,6 +1245,19 @@ static int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
                cctx->len_set = 0;
                return 1;
 
+       case EVP_CTRL_COPY:
+               {
+                       EVP_CIPHER_CTX *out = ptr;
+                       EVP_AES_CCM_CTX *cctx_out = out->cipher_data;
+                       if (cctx->ccm.key)
+                               {
+                               if (cctx->ccm.key != &cctx->ks)
+                                       return 0;
+                               cctx_out->ccm.key = &cctx_out->ks;
+                               }
+                       return 1;
+               }
+
        default:
                return -1;