123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- /*
- * Copyright 1995-2021 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
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
- /*
- * DES low level APIs are deprecated for public use, but still ok for internal
- * use.
- */
- #include "internal/deprecated.h"
- #include <stdio.h>
- #include "internal/cryptlib.h"
- #ifndef OPENSSL_NO_DES
- # include <openssl/objects.h>
- # include "crypto/evp.h"
- # include "crypto/sha.h"
- # include <openssl/des.h>
- # include <openssl/rand.h>
- # include "evp_local.h"
- typedef struct {
- union {
- OSSL_UNION_ALIGN;
- DES_key_schedule ks[3];
- } ks;
- union {
- void (*cbc) (const void *, void *, size_t,
- const DES_key_schedule *, unsigned char *);
- } stream;
- } DES_EDE_KEY;
- # define ks1 ks.ks[0]
- # define ks2 ks.ks[1]
- # define ks3 ks.ks[2]
- # if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
- /* ---------^^^ this is not a typo, just a way to detect that
- * assembler support was in general requested... */
- # include "crypto/sparc_arch.h"
- # define SPARC_DES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_DES)
- void des_t4_key_expand(const void *key, DES_key_schedule *ks);
- void des_t4_ede3_cbc_encrypt(const void *inp, void *out, size_t len,
- const DES_key_schedule ks[3], unsigned char iv[8]);
- void des_t4_ede3_cbc_decrypt(const void *inp, void *out, size_t len,
- const DES_key_schedule ks[3], unsigned char iv[8]);
- # endif
- static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
- const unsigned char *iv, int enc);
- static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
- const unsigned char *iv, int enc);
- static int des3_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr);
- # define data(ctx) EVP_C_DATA(DES_EDE_KEY,ctx)
- /*
- * Because of various casts and different args can't use
- * IMPLEMENT_BLOCK_CIPHER
- */
- static int des_ede_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
- {
- BLOCK_CIPHER_ecb_loop()
- DES_ecb3_encrypt((const_DES_cblock *)(in + i),
- (DES_cblock *)(out + i),
- &data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3, EVP_CIPHER_CTX_is_encrypting(ctx));
- return 1;
- }
- static int des_ede_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
- {
- while (inl >= EVP_MAXCHUNK) {
- int num = EVP_CIPHER_CTX_get_num(ctx);
- DES_ede3_ofb64_encrypt(in, out, (long)EVP_MAXCHUNK,
- &data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3,
- (DES_cblock *)ctx->iv,
- &num);
- EVP_CIPHER_CTX_set_num(ctx, num);
- inl -= EVP_MAXCHUNK;
- in += EVP_MAXCHUNK;
- out += EVP_MAXCHUNK;
- }
- if (inl) {
- int num = EVP_CIPHER_CTX_get_num(ctx);
- DES_ede3_ofb64_encrypt(in, out, (long)inl,
- &data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3,
- (DES_cblock *)ctx->iv,
- &num);
- EVP_CIPHER_CTX_set_num(ctx, num);
- }
- return 1;
- }
- static int des_ede_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
- {
- DES_EDE_KEY *dat = data(ctx);
- if (dat->stream.cbc != NULL) {
- (*dat->stream.cbc) (in, out, inl, dat->ks.ks,
- ctx->iv);
- return 1;
- }
- while (inl >= EVP_MAXCHUNK) {
- DES_ede3_cbc_encrypt(in, out, (long)EVP_MAXCHUNK,
- &dat->ks1, &dat->ks2, &dat->ks3,
- (DES_cblock *)ctx->iv,
- EVP_CIPHER_CTX_is_encrypting(ctx));
- inl -= EVP_MAXCHUNK;
- in += EVP_MAXCHUNK;
- out += EVP_MAXCHUNK;
- }
- if (inl)
- DES_ede3_cbc_encrypt(in, out, (long)inl,
- &dat->ks1, &dat->ks2, &dat->ks3,
- (DES_cblock *)ctx->iv,
- EVP_CIPHER_CTX_is_encrypting(ctx));
- return 1;
- }
- static int des_ede_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
- {
- while (inl >= EVP_MAXCHUNK) {
- int num = EVP_CIPHER_CTX_get_num(ctx);
- DES_ede3_cfb64_encrypt(in, out, (long)EVP_MAXCHUNK,
- &data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3, (DES_cblock *)ctx->iv,
- &num, EVP_CIPHER_CTX_is_encrypting(ctx));
- EVP_CIPHER_CTX_set_num(ctx, num);
- inl -= EVP_MAXCHUNK;
- in += EVP_MAXCHUNK;
- out += EVP_MAXCHUNK;
- }
- if (inl) {
- int num = EVP_CIPHER_CTX_get_num(ctx);
- DES_ede3_cfb64_encrypt(in, out, (long)inl,
- &data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3, (DES_cblock *)ctx->iv,
- &num, EVP_CIPHER_CTX_is_encrypting(ctx));
- EVP_CIPHER_CTX_set_num(ctx, num);
- }
- return 1;
- }
- /*
- * Although we have a CFB-r implementation for 3-DES, it doesn't pack the
- * right way, so wrap it here
- */
- static int des_ede3_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
- {
- size_t n;
- unsigned char c[1];
- unsigned char d[1] = { 0 }; /* Appease Coverity */
- if (!EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS))
- inl *= 8;
- for (n = 0; n < inl; ++n) {
- c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0;
- DES_ede3_cfb_encrypt(c, d, 1, 1,
- &data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3, (DES_cblock *)ctx->iv,
- EVP_CIPHER_CTX_is_encrypting(ctx));
- out[n / 8] = (out[n / 8] & ~(0x80 >> (unsigned int)(n % 8)))
- | ((d[0] & 0x80) >> (unsigned int)(n % 8));
- }
- return 1;
- }
- static int des_ede3_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
- {
- while (inl >= EVP_MAXCHUNK) {
- DES_ede3_cfb_encrypt(in, out, 8, (long)EVP_MAXCHUNK,
- &data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3, (DES_cblock *)ctx->iv,
- EVP_CIPHER_CTX_is_encrypting(ctx));
- inl -= EVP_MAXCHUNK;
- in += EVP_MAXCHUNK;
- out += EVP_MAXCHUNK;
- }
- if (inl)
- DES_ede3_cfb_encrypt(in, out, 8, (long)inl,
- &data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3, (DES_cblock *)ctx->iv,
- EVP_CIPHER_CTX_is_encrypting(ctx));
- return 1;
- }
- BLOCK_CIPHER_defs(des_ede, DES_EDE_KEY, NID_des_ede, 8, 16, 8, 64,
- EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_DEFAULT_ASN1,
- des_ede_init_key, NULL, NULL, NULL, des3_ctrl)
- # define des_ede3_cfb64_cipher des_ede_cfb64_cipher
- # define des_ede3_ofb_cipher des_ede_ofb_cipher
- # define des_ede3_cbc_cipher des_ede_cbc_cipher
- # define des_ede3_ecb_cipher des_ede_ecb_cipher
- BLOCK_CIPHER_defs(des_ede3, DES_EDE_KEY, NID_des_ede3, 8, 24, 8, 64,
- EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_DEFAULT_ASN1,
- des_ede3_init_key, NULL, NULL, NULL, des3_ctrl)
- BLOCK_CIPHER_def_cfb(des_ede3, DES_EDE_KEY, NID_des_ede3, 24, 8, 1,
- EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_DEFAULT_ASN1,
- des_ede3_init_key, NULL, NULL, NULL, des3_ctrl)
- BLOCK_CIPHER_def_cfb(des_ede3, DES_EDE_KEY, NID_des_ede3, 24, 8, 8,
- EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_DEFAULT_ASN1,
- des_ede3_init_key, NULL, NULL, NULL, des3_ctrl)
- static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
- const unsigned char *iv, int enc)
- {
- DES_cblock *deskey = (DES_cblock *)key;
- DES_EDE_KEY *dat = data(ctx);
- dat->stream.cbc = NULL;
- # if defined(SPARC_DES_CAPABLE)
- if (SPARC_DES_CAPABLE) {
- int mode = EVP_CIPHER_CTX_get_mode(ctx);
- if (mode == EVP_CIPH_CBC_MODE) {
- des_t4_key_expand(&deskey[0], &dat->ks1);
- des_t4_key_expand(&deskey[1], &dat->ks2);
- memcpy(&dat->ks3, &dat->ks1, sizeof(dat->ks1));
- dat->stream.cbc = enc ? des_t4_ede3_cbc_encrypt :
- des_t4_ede3_cbc_decrypt;
- return 1;
- }
- }
- # endif
- DES_set_key_unchecked(&deskey[0], &dat->ks1);
- DES_set_key_unchecked(&deskey[1], &dat->ks2);
- memcpy(&dat->ks3, &dat->ks1, sizeof(dat->ks1));
- return 1;
- }
- static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
- const unsigned char *iv, int enc)
- {
- DES_cblock *deskey = (DES_cblock *)key;
- DES_EDE_KEY *dat = data(ctx);
- dat->stream.cbc = NULL;
- # if defined(SPARC_DES_CAPABLE)
- if (SPARC_DES_CAPABLE) {
- int mode = EVP_CIPHER_CTX_get_mode(ctx);
- if (mode == EVP_CIPH_CBC_MODE) {
- des_t4_key_expand(&deskey[0], &dat->ks1);
- des_t4_key_expand(&deskey[1], &dat->ks2);
- des_t4_key_expand(&deskey[2], &dat->ks3);
- dat->stream.cbc = enc ? des_t4_ede3_cbc_encrypt :
- des_t4_ede3_cbc_decrypt;
- return 1;
- }
- }
- # endif
- DES_set_key_unchecked(&deskey[0], &dat->ks1);
- DES_set_key_unchecked(&deskey[1], &dat->ks2);
- DES_set_key_unchecked(&deskey[2], &dat->ks3);
- return 1;
- }
- static int des3_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
- {
- DES_cblock *deskey = ptr;
- int kl;
- switch (type) {
- case EVP_CTRL_RAND_KEY:
- kl = EVP_CIPHER_CTX_get_key_length(ctx);
- if (kl < 0 || RAND_priv_bytes(ptr, kl) <= 0)
- return 0;
- DES_set_odd_parity(deskey);
- if (kl >= 16)
- DES_set_odd_parity(deskey + 1);
- if (kl >= 24)
- DES_set_odd_parity(deskey + 2);
- return 1;
- default:
- return -1;
- }
- }
- const EVP_CIPHER *EVP_des_ede(void)
- {
- return &des_ede_ecb;
- }
- const EVP_CIPHER *EVP_des_ede3(void)
- {
- return &des_ede3_ecb;
- }
- # include <openssl/sha.h>
- static const unsigned char wrap_iv[8] =
- { 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05 };
- static int des_ede3_unwrap(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
- {
- unsigned char icv[8], iv[8], sha1tmp[SHA_DIGEST_LENGTH];
- int rv = -1;
- if (inl < 24)
- return -1;
- if (out == NULL)
- return inl - 16;
- memcpy(ctx->iv, wrap_iv, 8);
- /* Decrypt first block which will end up as icv */
- des_ede_cbc_cipher(ctx, icv, in, 8);
- /* Decrypt central blocks */
- /*
- * If decrypting in place move whole output along a block so the next
- * des_ede_cbc_cipher is in place.
- */
- if (out == in) {
- memmove(out, out + 8, inl - 8);
- in -= 8;
- }
- des_ede_cbc_cipher(ctx, out, in + 8, inl - 16);
- /* Decrypt final block which will be IV */
- des_ede_cbc_cipher(ctx, iv, in + inl - 8, 8);
- /* Reverse order of everything */
- BUF_reverse(icv, NULL, 8);
- BUF_reverse(out, NULL, inl - 16);
- BUF_reverse(ctx->iv, iv, 8);
- /* Decrypt again using new IV */
- des_ede_cbc_cipher(ctx, out, out, inl - 16);
- des_ede_cbc_cipher(ctx, icv, icv, 8);
- if (ossl_sha1(out, inl - 16, sha1tmp) /* Work out hash of first portion */
- && CRYPTO_memcmp(sha1tmp, icv, 8) == 0)
- rv = inl - 16;
- OPENSSL_cleanse(icv, 8);
- OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH);
- OPENSSL_cleanse(iv, 8);
- OPENSSL_cleanse(ctx->iv, 8);
- if (rv == -1)
- OPENSSL_cleanse(out, inl - 16);
- return rv;
- }
- static int des_ede3_wrap(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
- {
- unsigned char sha1tmp[SHA_DIGEST_LENGTH];
- if (out == NULL)
- return inl + 16;
- /* Copy input to output buffer + 8 so we have space for IV */
- memmove(out + 8, in, inl);
- /* Work out ICV */
- if (!ossl_sha1(in, inl, sha1tmp))
- return -1;
- memcpy(out + inl + 8, sha1tmp, 8);
- OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH);
- /* Generate random IV */
- if (RAND_bytes(ctx->iv, 8) <= 0)
- return -1;
- memcpy(out, ctx->iv, 8);
- /* Encrypt everything after IV in place */
- des_ede_cbc_cipher(ctx, out + 8, out + 8, inl + 8);
- BUF_reverse(out, NULL, inl + 16);
- memcpy(ctx->iv, wrap_iv, 8);
- des_ede_cbc_cipher(ctx, out, out, inl + 16);
- return inl + 16;
- }
- static int des_ede3_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
- {
- /*
- * Sanity check input length: we typically only wrap keys so EVP_MAXCHUNK
- * is more than will ever be needed. Also input length must be a multiple
- * of 8 bits.
- */
- if (inl >= EVP_MAXCHUNK || inl % 8)
- return -1;
- if (ossl_is_partially_overlapping(out, in, inl)) {
- ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
- return 0;
- }
- if (EVP_CIPHER_CTX_is_encrypting(ctx))
- return des_ede3_wrap(ctx, out, in, inl);
- else
- return des_ede3_unwrap(ctx, out, in, inl);
- }
- static const EVP_CIPHER des3_wrap = {
- NID_id_smime_alg_CMS3DESwrap,
- 8, 24, 0,
- EVP_CIPH_WRAP_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER
- | EVP_CIPH_FLAG_DEFAULT_ASN1,
- EVP_ORIG_GLOBAL,
- des_ede3_init_key, des_ede3_wrap_cipher,
- NULL,
- sizeof(DES_EDE_KEY),
- NULL, NULL, NULL, NULL
- };
- const EVP_CIPHER *EVP_des_ede3_wrap(void)
- {
- return &des3_wrap;
- }
- #endif
|