// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include "../des/internal.h" #include "../fipsmodule/cipher/internal.h" #include "internal.h" typedef struct { union { double align; DES_key_schedule ks; } ks; } EVP_DES_KEY; static int des_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, const uint8_t *iv, int enc) { EVP_DES_KEY *dat = (EVP_DES_KEY *)ctx->cipher_data; DES_set_key_ex(key, &dat->ks.ks); return 1; } static int des_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, size_t in_len) { EVP_DES_KEY *dat = (EVP_DES_KEY *)ctx->cipher_data; DES_ncbc_encrypt_ex(in, out, in_len, &dat->ks.ks, ctx->iv, ctx->encrypt); return 1; } static const EVP_CIPHER evp_des_cbc = { /*nid=*/NID_des_cbc, /*block_size=*/8, /*key_len=*/8, /*iv_len=*/8, /*ctx_size=*/sizeof(EVP_DES_KEY), /*flags=*/EVP_CIPH_CBC_MODE, /*init=*/des_init_key, /*cipher=*/des_cbc_cipher, /*cleanup=*/nullptr, /*ctrl=*/nullptr, }; const EVP_CIPHER *EVP_des_cbc(void) { return &evp_des_cbc; } static int des_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, size_t in_len) { if (in_len < ctx->cipher->block_size) { return 1; } in_len -= ctx->cipher->block_size; EVP_DES_KEY *dat = (EVP_DES_KEY *)ctx->cipher_data; for (size_t i = 0; i <= in_len; i += ctx->cipher->block_size) { DES_ecb_encrypt_ex(in + i, out + i, &dat->ks.ks, ctx->encrypt); } return 1; } static const EVP_CIPHER evp_des_ecb = { /*nid=*/NID_des_ecb, /*block_size=*/8, /*key_len=*/8, /*iv_len=*/0, /*ctx_size=*/sizeof(EVP_DES_KEY), /*flags=*/EVP_CIPH_ECB_MODE, /*init=*/des_init_key, /*cipher=*/des_ecb_cipher, /*cleanup=*/nullptr, /*ctrl=*/nullptr, }; const EVP_CIPHER *EVP_des_ecb(void) { return &evp_des_ecb; } typedef struct { union { double align; DES_key_schedule ks[3]; } ks; } DES_EDE_KEY; static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, const uint8_t *iv, int enc) { DES_EDE_KEY *dat = (DES_EDE_KEY *)ctx->cipher_data; DES_set_key_ex(key, &dat->ks.ks[0]); DES_set_key_ex(key + 8, &dat->ks.ks[1]); DES_set_key_ex(key + 16, &dat->ks.ks[2]); return 1; } static int des_ede3_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, size_t in_len) { DES_EDE_KEY *dat = (DES_EDE_KEY *)ctx->cipher_data; DES_ede3_cbc_encrypt_ex(in, out, in_len, &dat->ks.ks[0], &dat->ks.ks[1], &dat->ks.ks[2], ctx->iv, ctx->encrypt); return 1; } static const EVP_CIPHER evp_des_ede3_cbc = { /*nid=*/NID_des_ede3_cbc, /*block_size=*/8, /*key_len=*/24, /*iv_len=*/8, /*ctx_size=*/sizeof(DES_EDE_KEY), /*flags=*/EVP_CIPH_CBC_MODE, /*init=*/des_ede3_init_key, /*cipher=*/des_ede3_cbc_cipher, /*cleanup=*/nullptr, /*ctrl=*/nullptr, }; const EVP_CIPHER *EVP_des_ede3_cbc(void) { return &evp_des_ede3_cbc; } static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, const uint8_t *iv, int enc) { DES_EDE_KEY *dat = (DES_EDE_KEY *)ctx->cipher_data; // 2-DES is 3-DES with the first key used twice. DES_set_key_ex(key, &dat->ks.ks[0]); DES_set_key_ex(key + 8, &dat->ks.ks[1]); DES_set_key_ex(key, &dat->ks.ks[2]); return 1; } static const EVP_CIPHER evp_des_ede_cbc = { /*nid=*/NID_des_ede_cbc, /*block_size=*/8, /*key_len=*/16, /*iv_len=*/8, /*ctx_size=*/sizeof(DES_EDE_KEY), /*flags=*/EVP_CIPH_CBC_MODE, /*init=*/des_ede_init_key, /*cipher=*/des_ede3_cbc_cipher, /*cleanup=*/nullptr, /*ctrl=*/nullptr, }; const EVP_CIPHER *EVP_des_ede_cbc(void) { return &evp_des_ede_cbc; } static int des_ede_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, size_t in_len) { if (in_len < ctx->cipher->block_size) { return 1; } in_len -= ctx->cipher->block_size; DES_EDE_KEY *dat = (DES_EDE_KEY *)ctx->cipher_data; for (size_t i = 0; i <= in_len; i += ctx->cipher->block_size) { DES_ecb3_encrypt_ex(in + i, out + i, &dat->ks.ks[0], &dat->ks.ks[1], &dat->ks.ks[2], ctx->encrypt); } return 1; } static const EVP_CIPHER evp_des_ede = { /*nid=*/NID_des_ede_ecb, /*block_size=*/8, /*key_len=*/16, /*iv_len=*/0, /*ctx_size=*/sizeof(DES_EDE_KEY), /*flags=*/EVP_CIPH_ECB_MODE, /*init=*/des_ede_init_key, /*cipher=*/des_ede_ecb_cipher, /*cleanup=*/nullptr, /*ctrl=*/nullptr, }; const EVP_CIPHER *EVP_des_ede(void) { return &evp_des_ede; } static const EVP_CIPHER evp_des_ede3 = { /*nid=*/NID_des_ede3_ecb, /*block_size=*/8, /*key_len=*/24, /*iv_len=*/0, /*ctx_size=*/sizeof(DES_EDE_KEY), /*flags=*/EVP_CIPH_ECB_MODE, /*init=*/des_ede3_init_key, /*cipher=*/des_ede_ecb_cipher, /*cleanup=*/nullptr, /*ctrl=*/nullptr, }; const EVP_CIPHER *EVP_des_ede3(void) { return &evp_des_ede3; } const EVP_CIPHER *EVP_des_ede3_ecb(void) { return EVP_des_ede3(); }