// 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 #include "../des/internal.h" #include "../fipsmodule/cipher/internal.h" #include "internal.h" using namespace bssl; 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_update(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, size_t len) { EVP_DES_KEY *dat = (EVP_DES_KEY *)ctx->cipher_data; DES_ncbc_encrypt_ex(in, out, 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_update=*/des_cbc_cipher_update, /*cipher_final=*/nullptr, /*update_aad=*/nullptr, /*cleanup=*/nullptr, /*ctrl=*/nullptr, }; const EVP_CIPHER *EVP_des_cbc() { return &evp_des_cbc; } static int des_ecb_cipher_update(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, size_t len) { if (len < ctx->cipher->block_size) { return 1; } len -= ctx->cipher->block_size; EVP_DES_KEY *dat = (EVP_DES_KEY *)ctx->cipher_data; for (size_t i = 0; i <= 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_update=*/des_ecb_cipher_update, /*cipher_final=*/nullptr, /*update_aad=*/nullptr, /*cleanup=*/nullptr, /*ctrl=*/nullptr, }; const EVP_CIPHER *EVP_des_ecb() { 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_update(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, size_t len) { DES_EDE_KEY *dat = (DES_EDE_KEY *)ctx->cipher_data; DES_ede3_cbc_encrypt_ex(in, out, 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_update=*/des_ede3_cbc_cipher_update, /*cipher_final=*/nullptr, /*update_aad=*/nullptr, /*cleanup=*/nullptr, /*ctrl=*/nullptr, }; const EVP_CIPHER *EVP_des_ede3_cbc() { 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_update=*/des_ede3_cbc_cipher_update, /*cipher_final=*/nullptr, /*update_aad=*/nullptr, /*cleanup=*/nullptr, /*ctrl=*/nullptr, }; const EVP_CIPHER *EVP_des_ede_cbc() { return &evp_des_ede_cbc; } static int des_ede_ecb_cipher_update(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, size_t len) { if (len < ctx->cipher->block_size) { return 1; } len -= ctx->cipher->block_size; DES_EDE_KEY *dat = (DES_EDE_KEY *)ctx->cipher_data; for (size_t i = 0; i <= 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_update=*/des_ede_ecb_cipher_update, /*cipher_final=*/nullptr, /*update_aad=*/nullptr, /*cleanup=*/nullptr, /*ctrl=*/nullptr, }; const EVP_CIPHER *EVP_des_ede() { 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_update=*/des_ede_ecb_cipher_update, /*cipher_final=*/nullptr, /*update_aad=*/nullptr, /*cleanup=*/nullptr, /*ctrl=*/nullptr, }; const EVP_CIPHER *EVP_des_ede3() { return &evp_des_ede3; } const EVP_CIPHER *EVP_des_ede3_ecb() { return EVP_des_ede3(); }