From: Greg Hudson Date: Fri, 2 Oct 2009 15:33:56 +0000 (+0000) Subject: Merge trunk changes from r22791 to r22833 to enc-perf branch X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=afe943fe4d3092ce8d5e72e278997ca61833c367;p=thirdparty%2Fkrb5.git Merge trunk changes from r22791 to r22833 to enc-perf branch git-svn-id: svn://anonsvn.mit.edu/krb5/branches/enc-perf@22834 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/crypto/builtin/hash_provider/Makefile.in b/src/lib/crypto/builtin/hash_provider/Makefile.in index 75b3d1b0cb..a901d1175e 100644 --- a/src/lib/crypto/builtin/hash_provider/Makefile.in +++ b/src/lib/crypto/builtin/hash_provider/Makefile.in @@ -13,13 +13,23 @@ DEFS= PROG_LIBPATH=-L$(TOPLIBD) PROG_RPATH=$(KRB5_LIBDIR) -STLIBOBJS= hash_crc32.o hash_md4.o hash_md5.o hash_sha1.o - -OBJS= $(OUTPRE)hash_crc32.$(OBJEXT) $(OUTPRE)hash_md4.$(OBJEXT) \ - $(OUTPRE)hash_md5.$(OBJEXT) $(OUTPRE)hash_sha1.$(OBJEXT) - -SRCS= $(srcdir)/hash_crc32.c $(srcdir)/hash_md4.c \ - $(srcdir)/hash_md5.c $(srcdir)/hash_sha1.c +CIMPL = @CRYPTO_IMPL@/hash_provider + +STLIBOBJS= \ + ../../$(CIMPL)/hash_crc32.o \ + ../../$(CIMPL)/hash_md4.o \ + ../../$(CIMPL)/hash_md5.o \ + ../../$(CIMPL)/hash_sha1.o + +OBJS= $(OUTPRE)../../$(CIMPL)/hash_crc32.$(OBJEXT) \ + $(OUTPRE)../../$(CIMPL)/hash_md4.$(OBJEXT) \ + $(OUTPRE)../../$(CIMPL)/hash_md5.$(OBJEXT) \ + $(OUTPRE)../../$(CIMPL)/hash_sha1.$(OBJEXT) + +SRCS= $(srcdir)/../../$(CIMPL)/hash_crc32.c \ + $(srcdir)/../../$(CIMPL)/hash_md4.c \ + $(srcdir)/../../$(CIMPL)/hash_md5.c \ + $(srcdir)/../../$(CIMPL)/hash_sha1.c ##DOS##LIBOBJS = $(OBJS) diff --git a/src/lib/crypto/openssl/arcfour/arcfour-int.h b/src/lib/crypto/openssl/arcfour/arcfour-int.h new file mode 100644 index 0000000000..d9db0be8a7 --- /dev/null +++ b/src/lib/crypto/openssl/arcfour/arcfour-int.h @@ -0,0 +1,35 @@ +/* + +ARCFOUR cipher (based on a cipher posted on the Usenet in Spring-95). +This cipher is widely believed and has been tested to be equivalent +with the RC4 cipher from RSA Data Security, Inc. (RC4 is a trademark +of RSA Data Security) + +*/ +#ifndef ARCFOUR_INT_H +#define ARCFOUR_INT_H + +#include "arcfour.h" +#include + +#define CONFOUNDERLENGTH 8 + +typedef struct +{ + EVP_CIPHER_CTX evp_ctx; + unsigned int x; + unsigned int y; + unsigned char state[256]; + +} ArcfourContext; + +typedef struct { + int initialized; + ArcfourContext ctx; +} ArcFourCipherState; + +krb5_keyusage krb5int_arcfour_translate_usage(krb5_keyusage usage); + +extern const char *const krb5int_arcfour_l40; + +#endif /* ARCFOUR_INT_H */ diff --git a/src/lib/crypto/openssl/arcfour/arcfour.c b/src/lib/crypto/openssl/arcfour/arcfour.c new file mode 100644 index 0000000000..687f276b01 --- /dev/null +++ b/src/lib/crypto/openssl/arcfour/arcfour.c @@ -0,0 +1,326 @@ +/* + +ARCFOUR cipher (based on a cipher posted on the Usenet in Spring-95). +This cipher is widely believed and has been tested to be equivalent +with the RC4 cipher from RSA Data Security, Inc. (RC4 is a trademark +of RSA Data Security) + +*/ +#include "k5-int.h" +#include "arcfour-int.h" +#include "hash_provider/hash_provider.h" + +const char *const krb5int_arcfour_l40 = "fortybits"; + +void +krb5_arcfour_encrypt_length(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + size_t inputlen, size_t *length) +{ + size_t blocksize, hashsize; + + blocksize = enc->block_size; + hashsize = hash->hashsize; + + /* checksum + (confounder + inputlen, in even blocksize) */ + *length = hashsize + krb5_roundup(8 + inputlen, blocksize); +} + + krb5_keyusage + krb5int_arcfour_translate_usage(krb5_keyusage usage) +{ + switch (usage) { + case 1: /* AS-REQ PA-ENC-TIMESTAMP padata timestamp, */ + return 1; + case 2: /* ticket from kdc */ + return 2; + case 3: /* as-rep encrypted part */ + return 8; + case 4: /* tgs-req authz data */ + return 4; + case 5: /* tgs-req authz data in subkey */ + return 5; + case 6: /* tgs-req authenticator cksum */ + return 6; +case 7: /* tgs-req authenticator */ + return 7; + case 8: + return 8; + case 9: /* tgs-rep encrypted with subkey */ + return 9; + case 10: /* ap-rep authentication cksum */ + return 10; /* xxx Microsoft never uses this*/ + case 11: /* app-req authenticator */ + return 11; + case 12: /* app-rep encrypted part */ + return 12; + case 23: /* sign wrap token*/ + return 13; + default: + return usage; +} +} + +/* RFC 4757 */ +krb5_error_code +krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, krb5_keyusage usage, + const krb5_data *ivec, const krb5_data *input, + krb5_data *output) +{ + krb5_keyblock k1, k2, k3; + krb5_data d1, d2, d3, salt, plaintext, checksum, ciphertext, confounder; + krb5_keyusage ms_usage; + size_t keylength, keybytes, blocksize, hashsize; + krb5_error_code ret; + + blocksize = enc->block_size; + keybytes = enc->keybytes; + keylength = enc->keylength; + hashsize = hash->hashsize; + + d1.length=keybytes; + d1.data=malloc(d1.length); + if (d1.data == NULL) + return (ENOMEM); + k1 = *key; + k1.length=d1.length; + k1.contents= (void *) d1.data; + + d2.length=keybytes; + d2.data=malloc(d2.length); + if (d2.data == NULL) { + free(d1.data); + return (ENOMEM); + } + k2 = *key; + k2.length=d2.length; + k2.contents=(void *) d2.data; + + d3.length=keybytes; + d3.data=malloc(d3.length); + if (d3.data == NULL) { + free(d1.data); + free(d2.data); + return (ENOMEM); + } + k3 = *key; + k3.length=d3.length; + k3.contents= (void *) d3.data; + + salt.length=14; + salt.data=malloc(salt.length); + if (salt.data == NULL) { + free(d1.data); + free(d2.data); + free(d3.data); + return (ENOMEM); + } + + /* is "input" already blocksize aligned? if it is, then we need this + step, otherwise we do not */ + plaintext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize); + plaintext.data=malloc(plaintext.length); + if (plaintext.data == NULL) { + free(d1.data); + free(d2.data); + free(d3.data); + free(salt.data); + return(ENOMEM); + } + + /* setup convienient pointers into the allocated data */ + checksum.length=hashsize; + checksum.data=output->data; + ciphertext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize); + ciphertext.data=output->data+hashsize; + confounder.length=CONFOUNDERLENGTH; + confounder.data=plaintext.data; + output->length = plaintext.length+hashsize; + + /* begin the encryption, computer K1 */ + ms_usage=krb5int_arcfour_translate_usage(usage); + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + strncpy(salt.data, krb5int_arcfour_l40, salt.length); + store_32_le(ms_usage, salt.data+10); + } else { + salt.length=4; + store_32_le(ms_usage, salt.data); + } + krb5_hmac(hash, key, 1, &salt, &d1); + + memcpy(k2.contents, k1.contents, k2.length); + + if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) + memset(k1.contents+7, 0xab, 9); + + ret=krb5_c_random_make_octets(/* XXX */ 0, &confounder); + memcpy(plaintext.data+confounder.length, input->data, input->length); + if (ret) + goto cleanup; + + krb5_hmac(hash, &k2, 1, &plaintext, &checksum); + + krb5_hmac(hash, &k1, 1, &checksum, &d3); + + ret=(*(enc->encrypt))(&k3, ivec, &plaintext, &ciphertext); + + cleanup: + memset(d1.data, 0, d1.length); + memset(d2.data, 0, d2.length); + memset(d3.data, 0, d3.length); + memset(salt.data, 0, salt.length); + memset(plaintext.data, 0, plaintext.length); + + free(d1.data); + free(d2.data); + free(d3.data); + free(salt.data); + free(plaintext.data); + return (ret); +} + +/* This is the arcfour-hmac decryption routine */ +krb5_error_code +krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, krb5_keyusage usage, + const krb5_data *ivec, const krb5_data *input, + krb5_data *output) +{ + krb5_keyblock k1,k2,k3; + krb5_data d1,d2,d3,salt,ciphertext,plaintext,checksum; + krb5_keyusage ms_usage; + size_t keybytes, keylength, hashsize, blocksize; + krb5_error_code ret; + + blocksize = enc->block_size; + keybytes = enc->keybytes; + keylength = enc->keylength; + hashsize = hash->hashsize; + + d1.length=keybytes; + d1.data=malloc(d1.length); + if (d1.data == NULL) + return (ENOMEM); + k1 = *key; + k1.length=d1.length; + k1.contents= (void *) d1.data; + + d2.length=keybytes; + d2.data=malloc(d2.length); + if (d2.data == NULL) { + free(d1.data); + return (ENOMEM); + } + k2 = *key; + k2.length=d2.length; + k2.contents= (void *) d2.data; + + d3.length=keybytes; + d3.data=malloc(d3.length); + if (d3.data == NULL) { + free(d1.data); + free(d2.data); + return (ENOMEM); + } + k3 = *key; + k3.length=d3.length; + k3.contents= (void *) d3.data; + + salt.length=14; + salt.data=malloc(salt.length); + if(salt.data==NULL) { + free(d1.data); + free(d2.data); + free(d3.data); + return (ENOMEM); + } + + ciphertext.length=input->length-hashsize; + ciphertext.data=input->data+hashsize; + plaintext.length=ciphertext.length; + plaintext.data=malloc(plaintext.length); + if (plaintext.data == NULL) { + free(d1.data); + free(d2.data); + free(d3.data); + free(salt.data); + return (ENOMEM); + } + + checksum.length=hashsize; + checksum.data=input->data; + + ms_usage=krb5int_arcfour_translate_usage(usage); + + /* We may have to try two ms_usage values; see below. */ + do { + /* compute the salt */ + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + strncpy(salt.data, krb5int_arcfour_l40, salt.length); + store_32_le(ms_usage, salt.data + 10); + } else { + salt.length = 4; + store_32_le(ms_usage, salt.data); + } + ret = krb5_hmac(hash, key, 1, &salt, &d1); + if (ret) + goto cleanup; + + memcpy(k2.contents, k1.contents, k2.length); + + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + memset(k1.contents + 7, 0xab, 9); + + ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); + if (ret) + goto cleanup; + + ret = (*(enc->decrypt))(&k3, ivec, &ciphertext, &plaintext); + if (ret) + goto cleanup; + + ret = krb5_hmac(hash, &k2, 1, &plaintext, &d1); + if (ret) + goto cleanup; + + if (memcmp(checksum.data, d1.data, hashsize) != 0) { + if (ms_usage == 9) { + /* + * RFC 4757 specifies usage 8 for TGS-REP encrypted + * parts encrypted in a subkey, but the value used by MS + * is actually 9. We now use 9 to start with, but fall + * back to 8 on failure in case we are communicating + * with a KDC using the value from the RFC. + */ + ms_usage = 8; + continue; + } + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + + break; + } while (1); + + memcpy(output->data, plaintext.data+CONFOUNDERLENGTH, + (plaintext.length-CONFOUNDERLENGTH)); + output->length=plaintext.length-CONFOUNDERLENGTH; + + cleanup: + memset(d1.data, 0, d1.length); + memset(d2.data, 0, d2.length); + memset(d3.data, 0, d2.length); + memset(salt.data, 0, salt.length); + memset(plaintext.data, 0, plaintext.length); + + free(d1.data); + free(d2.data); + free(d3.data); + free(salt.data); + free(plaintext.data); + return (ret); +} + diff --git a/src/lib/crypto/openssl/arcfour/arcfour.h b/src/lib/crypto/openssl/arcfour/arcfour.h new file mode 100644 index 0000000000..be408febc6 --- /dev/null +++ b/src/lib/crypto/openssl/arcfour/arcfour.h @@ -0,0 +1,43 @@ +#ifndef ARCFOUR_H +#define ARCFOUR_H + +extern void +krb5_arcfour_encrypt_length(const struct krb5_enc_provider *, + const struct krb5_hash_provider *, + size_t, + size_t *); + +extern +krb5_error_code krb5_arcfour_encrypt(const struct krb5_enc_provider *, + const struct krb5_hash_provider *, + const krb5_keyblock *, + krb5_keyusage, + const krb5_data *, + const krb5_data *, + krb5_data *); + +extern +krb5_error_code krb5_arcfour_decrypt(const struct krb5_enc_provider *, + const struct krb5_hash_provider *, + const krb5_keyblock *, + krb5_keyusage, + const krb5_data *, + const krb5_data *, + krb5_data *); + +extern krb5_error_code krb5int_arcfour_string_to_key( + const struct krb5_enc_provider *, + const krb5_data *, + const krb5_data *, + const krb5_data *, + krb5_keyblock *); + +extern const struct krb5_enc_provider krb5int_enc_arcfour; +extern const struct krb5_aead_provider krb5int_aead_arcfour; + krb5_error_code krb5int_arcfour_prf( + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + const krb5_data *in, krb5_data *out); + +#endif /* ARCFOUR_H */ diff --git a/src/lib/crypto/openssl/arcfour/arcfour_aead.c b/src/lib/crypto/openssl/arcfour/arcfour_aead.c new file mode 100644 index 0000000000..cff7d66d65 --- /dev/null +++ b/src/lib/crypto/openssl/arcfour/arcfour_aead.c @@ -0,0 +1,325 @@ +/* + * lib/crypto/arcfour/arcfour_aead.c + * + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + + +#include "k5-int.h" +#include "arcfour.h" +#include "arcfour-int.h" +#include "aead.h" + +/* AEAD */ + +static krb5_error_code +krb5int_arcfour_crypto_length(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_cryptotype type, + unsigned int *length) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_HEADER: + *length = hash->hashsize + CONFOUNDERLENGTH; + break; + case KRB5_CRYPTO_TYPE_PADDING: + *length = 0; + break; + case KRB5_CRYPTO_TYPE_TRAILER: + *length = 0; + break; + case KRB5_CRYPTO_TYPE_CHECKSUM: + *length = hash->hashsize; + break; + default: + assert(0 && "invalid cryptotype passed to krb5int_arcfour_crypto_length"); + break; + } + + return 0; +} + +static krb5_error_code +alloc_derived_key(const struct krb5_enc_provider *enc, + krb5_keyblock *dst, + krb5_data *data, + const krb5_keyblock *src) +{ + data->length = enc->keybytes; + data->data = malloc(data->length); + if (data->data == NULL) + return ENOMEM; + + *dst = *src; + dst->length = data->length; + dst->contents = (void *)data->data; + + return 0; +} + +static krb5_error_code +krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_error_code ret; + krb5_crypto_iov *header, *trailer; + krb5_keyblock k1, k2, k3; + krb5_data d1, d2, d3; + krb5_data checksum, confounder, header_data; + krb5_keyusage ms_usage; + char salt_data[14]; + krb5_data salt; + size_t i; + + d1.length = d2.length = d3.length = 0; + d1.data = d2.data = d3.data = NULL; + + /* + * Caller must have provided space for the header, padding + * and trailer; per RFC 4757 we will arrange it as: + * + * Checksum | E(Confounder | Plaintext) + */ + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || + header->data.length < hash->hashsize + CONFOUNDERLENGTH) + return KRB5_BAD_MSIZE; + + header_data = header->data; + + /* Trailer may be absent */ + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer != NULL) + trailer->data.length = 0; + + /* Ensure that there is no padding */ + for (i = 0; i < num_data; i++) { + if (data[i].flags == KRB5_CRYPTO_TYPE_PADDING) + data[i].data.length = 0; + } + + ret = alloc_derived_key(enc, &k1, &d1, key); + if (ret != 0) + goto cleanup; + + ret = alloc_derived_key(enc, &k2, &d2, key); + if (ret != 0) + goto cleanup; + + ret = alloc_derived_key(enc, &k3, &d3, key); + if (ret != 0) + goto cleanup; + + /* Begin the encryption, compute K1 */ + salt.data = salt_data; + salt.length = sizeof(salt_data); + + ms_usage = krb5int_arcfour_translate_usage(usage); + + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + strncpy(salt.data, krb5int_arcfour_l40, salt.length); + store_32_le(ms_usage, salt.data + 10); + } else { + salt.length = 4; + store_32_le(ms_usage, salt.data); + } + ret = krb5_hmac(hash, key, 1, &salt, &d1); + if (ret != 0) + goto cleanup; + + memcpy(k2.contents, k1.contents, k2.length); + + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + memset(k1.contents + 7, 0xAB, 9); + + header->data.length = hash->hashsize + CONFOUNDERLENGTH; + + confounder.data = header->data.data + hash->hashsize; + confounder.length = CONFOUNDERLENGTH; + + ret = krb5_c_random_make_octets(0, &confounder); + if (ret != 0) + goto cleanup; + + checksum.data = header->data.data; + checksum.length = hash->hashsize; + + /* Adjust pointers so confounder is at start of header */ + header->data.length -= hash->hashsize; + header->data.data += hash->hashsize; + + ret = krb5int_hmac_iov(hash, &k2, data, num_data, &checksum); + if (ret != 0) + goto cleanup; + + ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); + if (ret != 0) + goto cleanup; + + ret = enc->encrypt_iov(&k3, ivec, data, num_data); + if (ret != 0) + goto cleanup; + +cleanup: + header->data = header_data; /* restore header pointers */ + + if (d1.data != NULL) { + memset(d1.data, 0, d1.length); + free(d1.data); + } + if (d2.data != NULL) { + memset(d2.data, 0, d2.length); + free(d2.data); + } + if (d3.data != NULL) { + memset(d3.data, 0, d3.length); + free(d3.data); + } + + return ret; +} + +static krb5_error_code +krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_error_code ret; + krb5_crypto_iov *header, *trailer; + krb5_keyblock k1, k2, k3; + krb5_data d1, d2, d3; + krb5_data checksum, header_data; + krb5_keyusage ms_usage; + char salt_data[14]; + krb5_data salt; + + d1.length = d2.length = d3.length = 0; + d1.data = d2.data = d3.data = NULL; + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || + header->data.length != hash->hashsize + CONFOUNDERLENGTH) + return KRB5_BAD_MSIZE; + + header_data = header->data; + + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer != NULL && trailer->data.length != 0) + return KRB5_BAD_MSIZE; + + ret = alloc_derived_key(enc, &k1, &d1, key); + if (ret != 0) + goto cleanup; + + ret = alloc_derived_key(enc, &k2, &d2, key); + if (ret != 0) + goto cleanup; + + ret = alloc_derived_key(enc, &k3, &d3, key); + if (ret != 0) + goto cleanup; + + /* Begin the decryption, compute K1 */ + salt.data = salt_data; + salt.length = sizeof(salt_data); + + ms_usage = krb5int_arcfour_translate_usage(usage); + + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + strncpy(salt.data, krb5int_arcfour_l40, salt.length); + store_32_le(ms_usage, (unsigned char *)salt.data + 10); + } else { + salt.length = 4; + store_32_le(ms_usage, (unsigned char *)salt.data); + } + ret = krb5_hmac(hash, key, 1, &salt, &d1); + if (ret != 0) + goto cleanup; + + memcpy(k2.contents, k1.contents, k2.length); + + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + memset(k1.contents + 7, 0xAB, 9); + + checksum.data = header->data.data; + checksum.length = hash->hashsize; + + /* Adjust pointers so confounder is at start of header */ + header->data.length -= hash->hashsize; + header->data.data += hash->hashsize; + + ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); + if (ret != 0) + goto cleanup; + + ret = enc->decrypt_iov(&k3, ivec, data, num_data); + if (ret != 0) + goto cleanup; + + ret = krb5int_hmac_iov(hash, &k2, data, num_data, &d1); + if (ret != 0) + goto cleanup; + + if (memcmp(checksum.data, d1.data, hash->hashsize) != 0) { + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + +cleanup: + header->data = header_data; /* restore header pointers */ + + if (d1.data != NULL) { + memset(d1.data, 0, d1.length); + free(d1.data); + } + if (d2.data != NULL) { + memset(d2.data, 0, d2.length); + free(d2.data); + } + if (d3.data != NULL) { + memset(d3.data, 0, d3.length); + free(d3.data); + } + + return ret; +} + +const struct krb5_aead_provider krb5int_aead_arcfour = { + krb5int_arcfour_crypto_length, + krb5int_arcfour_encrypt_iov, + krb5int_arcfour_decrypt_iov +}; + diff --git a/src/lib/crypto/openssl/arcfour/arcfour_s2k.c b/src/lib/crypto/openssl/arcfour/arcfour_s2k.c new file mode 100644 index 0000000000..41053ed17d --- /dev/null +++ b/src/lib/crypto/openssl/arcfour/arcfour_s2k.c @@ -0,0 +1,59 @@ +#include "k5-int.h" +#include "k5-utf8.h" +#include "rsa-md4.h" +#include "arcfour-int.h" + +#if TARGET_OS_MAC && !defined(DEPEND) +#include +#endif + +krb5_error_code +krb5int_arcfour_string_to_key(const struct krb5_enc_provider *enc, + const krb5_data *string, const krb5_data *salt, + const krb5_data *params, krb5_keyblock *key) +{ + krb5_error_code err = 0; + krb5_MD4_CTX md4_context; + unsigned char *copystr; + size_t copystrlen; + + if (params != NULL) + return KRB5_ERR_BAD_S2K_PARAMS; + + if (key->length != 16) + return (KRB5_BAD_MSIZE); + + /* We ignore salt per the Microsoft spec*/ + + /* compute the space needed for the new string. + Since the password must be stored in unicode, we need to increase + that number by 2x. + */ + + err = krb5int_utf8cs_to_ucs2les(string->data, string->length, ©str, ©strlen); + if (err) + return err; + + /* the actual MD4 hash of the data */ + krb5_MD4Init(&md4_context); + krb5_MD4Update(&md4_context, copystr, copystrlen); + krb5_MD4Final(&md4_context); + memcpy(key->contents, md4_context.digest, 16); + +#if 0 + /* test the string_to_key function */ + printf("Hash="); + { + int counter; + for(counter=0;counter<16;counter++) + printf("%02x", md4_context.digest[counter]); + printf("\n"); + } +#endif /* 0 */ + + /* Zero out the data behind us */ + memset(copystr, 0, copystrlen); + memset(&md4_context, 0, sizeof(md4_context)); + free(copystr); + return err; +} diff --git a/src/lib/crypto/openssl/des/afsstring2key.c b/src/lib/crypto/openssl/des/afsstring2key.c new file mode 100644 index 0000000000..031db5845f --- /dev/null +++ b/src/lib/crypto/openssl/des/afsstring2key.c @@ -0,0 +1,27 @@ +/* lib/crypto/openss/des/afsstring2key.c + * + * Copyright 2009 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + */ + +#include "k5-int.h" +#include "des_int.h" +#include + +krb5_error_code +mit_afs_string_to_key (krb5_keyblock *keyblock, const krb5_data *data, + const krb5_data *salt) +{ + return KRB5_CRYPTO_INTERNAL; +} +char * +mit_afs_crypt(const char *pw, const char *salt, + char *iobuf) +{ + /* Unsupported operation */ + return NULL; +} + + diff --git a/src/lib/crypto/openssl/des/d3_aead.c b/src/lib/crypto/openssl/des/d3_aead.c new file mode 100644 index 0000000000..cd99886116 --- /dev/null +++ b/src/lib/crypto/openssl/des/d3_aead.c @@ -0,0 +1,34 @@ +/* lib/crypto/openssl/des/d3_aead.c + * + * Copyright 2009 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + */ +#include "des_int.h" +#include "aead.h" + +void +krb5int_des3_cbc_encrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + mit_des_cblock ivec) +{ + /* Unsupported operation */ + abort(); +} + +void +krb5int_des3_cbc_decrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + mit_des_cblock ivec) +{ + /* Unsupported operation */ + abort(); +} + diff --git a/src/lib/crypto/openssl/des/d3_cbc.c b/src/lib/crypto/openssl/des/d3_cbc.c new file mode 100644 index 0000000000..98caab5039 --- /dev/null +++ b/src/lib/crypto/openssl/des/d3_cbc.c @@ -0,0 +1,51 @@ +/* lib/crypto/openssl/des/d3_cbc.c + * + * Copyright 2009 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + */ +#include "des_int.h" + +/* + * Triple-DES CBC encryption mode. + */ + +#undef mit_des3_cbc_encrypt +int +mit_des3_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out, + unsigned long length, const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + const mit_des_cblock ivec, int enc) +{ + /* Unsupported operation */ + return KRB5_CRYPTO_INTERNAL; +} + +void +krb5int_des3_cbc_encrypt(const mit_des_cblock *input, + mit_des_cblock *output, + unsigned long length, + const mit_des_key_schedule key, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + const mit_des_cblock ivec) +{ + /* Unsupported operation */ + abort(); +} + +void +krb5int_des3_cbc_decrypt(const mit_des_cblock *in, + mit_des_cblock *out, + unsigned long length, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + const mit_des_cblock ivec) +{ + /* Unsupported operation */ + abort(); +} + diff --git a/src/lib/crypto/openssl/des/d3_kysched.c b/src/lib/crypto/openssl/des/d3_kysched.c new file mode 100644 index 0000000000..fb42e792f9 --- /dev/null +++ b/src/lib/crypto/openssl/des/d3_kysched.c @@ -0,0 +1,18 @@ +/* lib/crypto/openssl/des/d3_kysched.c + * + * Copyright 2009 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + */ + +#include "des_int.h" + +int +mit_des3_key_sched(mit_des3_cblock k, mit_des3_key_schedule schedule) +{ + /* Unsupported operation */ + return KRB5_CRYPTO_INTERNAL; +} + + diff --git a/src/lib/crypto/openssl/des/des_int.h b/src/lib/crypto/openssl/des/des_int.h new file mode 100644 index 0000000000..fd2024a454 --- /dev/null +++ b/src/lib/crypto/openssl/des/des_int.h @@ -0,0 +1,377 @@ +/* + * lib/crypto/des/des_int.h + * + * Copyright 1987, 1988, 1990, 2002 by the Massachusetts Institute of + * Technology. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * Private include file for the Data Encryption Standard library. + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* only do the whole thing once */ +#ifndef DES_INTERNAL_DEFS +#define DES_INTERNAL_DEFS + +#include "k5-int.h" +/* + * Begin "mit-des.h" + */ +#ifndef KRB5_MIT_DES__ +#define KRB5_MIT_DES__ + +#if defined(__MACH__) && defined(__APPLE__) +#include +#include +#if TARGET_RT_MAC_CFM +#error "Use KfM 4.0 SDK headers for CFM compilation." +#endif +#if defined(DEPRECATED_IN_MAC_OS_X_VERSION_10_5) && !defined(KRB5_SUPRESS_DEPRECATED_WARNINGS) +#define KRB5INT_DES_DEPRECATED DEPRECATED_IN_MAC_OS_X_VERSION_10_5 +#endif +#endif /* defined(__MACH__) && defined(__APPLE__) */ + +/* Macro to add deprecated attribute to DES types and functions */ +/* Currently only defined on Mac OS X 10.5 and later. */ +#ifndef KRB5INT_DES_DEPRECATED +#define KRB5INT_DES_DEPRECATED +#endif + +#include + +#if UINT_MAX >= 0xFFFFFFFFUL +#define DES_INT32 int +#define DES_UINT32 unsigned int +#else +#define DES_INT32 long +#define DES_UINT32 unsigned long +#endif + +typedef unsigned char des_cblock[8] /* crypto-block size */ +KRB5INT_DES_DEPRECATED; + +/* + * Key schedule. + * + * This used to be + * + * typedef struct des_ks_struct { + * union { DES_INT32 pad; des_cblock _;} __; + * } des_key_schedule[16]; + * + * but it would cause trouble if DES_INT32 were ever more than 4 + * bytes. The reason is that all the encryption functions cast it to + * (DES_INT32 *), and treat it as if it were DES_INT32[32]. If + * 2*sizeof(DES_INT32) is ever more than sizeof(des_cblock), the + * caller-allocated des_key_schedule will be overflowed by the key + * scheduling functions. We can't assume that every platform will + * have an exact 32-bit int, and nothing should be looking inside a + * des_key_schedule anyway. + */ +typedef struct des_ks_struct { DES_INT32 _[2]; } des_key_schedule[16] +KRB5INT_DES_DEPRECATED; + +typedef des_cblock mit_des_cblock; +typedef des_key_schedule mit_des_key_schedule; + +/* Triple-DES structures */ +typedef mit_des_cblock mit_des3_cblock[3]; +typedef mit_des_key_schedule mit_des3_key_schedule[3]; + +#define MIT_DES_ENCRYPT 1 +#define MIT_DES_DECRYPT 0 + +typedef struct mit_des_ran_key_seed { + krb5_encrypt_block eblock; + krb5_data sequence; +} mit_des_random_state; + +/* the first byte of the key is already in the keyblock */ + +#define MIT_DES_BLOCK_LENGTH (8*sizeof(krb5_octet)) +#define MIT_DES_CBC_CRC_PAD_MINIMUM CRC32_CKSUM_LENGTH +/* This used to be 8*sizeof(krb5_octet) */ +#define MIT_DES_KEYSIZE 8 + +#define MIT_DES_CBC_CKSUM_LENGTH (4*sizeof(krb5_octet)) + +/* + * Check if k5-int.h has been included before us. If so, then check to see + * that our view of the DES key size is the same as k5-int.h's. + */ +#ifdef KRB5_MIT_DES_KEYSIZE +#if MIT_DES_KEYSIZE != KRB5_MIT_DES_KEYSIZE +error(MIT_DES_KEYSIZE does not equal KRB5_MIT_DES_KEYSIZE) +#endif /* MIT_DES_KEYSIZE != KRB5_MIT_DES_KEYSIZE */ +#endif /* KRB5_MIT_DES_KEYSIZE */ +#endif /* KRB5_MIT_DES__ */ +/* + * End "mit-des.h" + */ + +/* afsstring2key.c */ +extern krb5_error_code mit_afs_string_to_key + (krb5_keyblock *keyblock, + const krb5_data *data, + const krb5_data *salt); +extern char *mit_afs_crypt + (const char *pw, const char *salt, char *iobuf); + +/* f_cksum.c */ +extern unsigned long mit_des_cbc_cksum + (const krb5_octet *, krb5_octet *, unsigned long , + const mit_des_key_schedule, const krb5_octet *); + +/* f_ecb.c */ +extern int mit_des_ecb_encrypt + (const mit_des_cblock *, mit_des_cblock *, mit_des_key_schedule , int ); + +/* f_cbc.c */ +extern int mit_des_cbc_encrypt (const mit_des_cblock *in, + mit_des_cblock *out, + unsigned long length, + const mit_des_key_schedule schedule, + const mit_des_cblock ivec, int enc); + +#define mit_des_zeroblock krb5int_c_mit_des_zeroblock +extern const mit_des_cblock mit_des_zeroblock; + +/* fin_rndkey.c */ +extern krb5_error_code mit_des_finish_random_key + ( const krb5_encrypt_block *, + krb5_pointer *); + +/* finish_key.c */ +extern krb5_error_code mit_des_finish_key + ( krb5_encrypt_block *); + +/* init_rkey.c */ +extern krb5_error_code mit_des_init_random_key + ( const krb5_encrypt_block *, + const krb5_keyblock *, + krb5_pointer *); + +/* key_parity.c */ +extern void mit_des_fixup_key_parity (mit_des_cblock ); +extern int mit_des_check_key_parity (mit_des_cblock ); + +/* key_sched.c */ +extern int mit_des_key_sched + (mit_des_cblock , mit_des_key_schedule ); + +/* process_ky.c */ +extern krb5_error_code mit_des_process_key + ( krb5_encrypt_block *, const krb5_keyblock *); + +/* random_key.c */ +extern krb5_error_code mit_des_random_key + ( const krb5_encrypt_block *, krb5_pointer , + krb5_keyblock **); + +/* string2key.c */ +extern krb5_error_code mit_des_string_to_key + ( const krb5_encrypt_block *, + krb5_keyblock *, const krb5_data *, const krb5_data *); +extern krb5_error_code mit_des_string_to_key_int + (krb5_keyblock *, const krb5_data *, const krb5_data *); + +/* weak_key.c */ +extern int mit_des_is_weak_key (mit_des_cblock ); + +/* cmb_keys.c */ +krb5_error_code mit_des_combine_subkeys + (const krb5_keyblock *, const krb5_keyblock *, + krb5_keyblock **); + +/* f_pcbc.c */ +int mit_des_pcbc_encrypt (); + +/* f_sched.c */ +int mit_des_make_key_sched(mit_des_cblock, mit_des_key_schedule); + + +/* misc.c */ +extern void swap_bits (char *); +extern unsigned long long_swap_bits (unsigned long ); +extern unsigned long swap_six_bits_to_ansi (unsigned long ); +extern unsigned long swap_four_bits_to_ansi (unsigned long ); +extern unsigned long swap_bit_pos_1 (unsigned long ); +extern unsigned long swap_bit_pos_0 (unsigned long ); +extern unsigned long swap_bit_pos_0_to_ansi (unsigned long ); +extern unsigned long rev_swap_bit_pos_0 (unsigned long ); +extern unsigned long swap_byte_bits (unsigned long ); +extern unsigned long swap_long_bytes_bit_number (unsigned long ); +#ifdef FILE +/* XXX depends on FILE being a #define! */ +extern void test_set (FILE *, const char *, int, const char *, int); +#endif + +/* d3_ecb.c */ +extern int mit_des3_ecb_encrypt + (const mit_des_cblock *in, + mit_des_cblock *out, + mit_des_key_schedule sched1, + mit_des_key_schedule sched2, + mit_des_key_schedule sched3, + int enc); + +/* d3_cbc.c */ +extern int mit_des3_cbc_encrypt + (const mit_des_cblock *in, + mit_des_cblock *out, + unsigned long length, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + const mit_des_cblock ivec, + int enc); + +void +krb5int_des3_cbc_encrypt(const mit_des_cblock *in, + mit_des_cblock *out, + unsigned long length, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + const mit_des_cblock ivec); +void +krb5int_des3_cbc_decrypt(const mit_des_cblock *in, + mit_des_cblock *out, + unsigned long length, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + const mit_des_cblock ivec); + +void +krb5int_des3_cbc_encrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + mit_des_cblock ivec); + +void +krb5int_des3_cbc_decrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + mit_des_cblock ivec); + +#define mit_des3_cbc_encrypt(in,out,length,ks1,ks2,ks3,ivec,enc) \ + ((enc ? krb5int_des3_cbc_encrypt : krb5int_des3_cbc_decrypt) \ + (in, out, length, ks1, ks2, ks3, ivec), 0) + +void +krb5int_des_cbc_encrypt(const mit_des_cblock *in, + mit_des_cblock *out, + unsigned long length, + const mit_des_key_schedule schedule, + const mit_des_cblock ivec); +void +krb5int_des_cbc_decrypt(const mit_des_cblock *in, + mit_des_cblock *out, + unsigned long length, + const mit_des_key_schedule schedule, + const mit_des_cblock ivec); + +#define mit_des_cbc_encrypt(in,out,length,schedule,ivec,enc) \ + ((enc ? krb5int_des_cbc_encrypt : krb5int_des_cbc_decrypt) \ + (in, out, length, schedule, ivec), 0) + +void +krb5int_des_cbc_encrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec); + +void +krb5int_des_cbc_decrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec); + +/* d3_procky.c */ +extern krb5_error_code mit_des3_process_key + (krb5_encrypt_block * eblock, + const krb5_keyblock * keyblock); + +/* d3_kysched.c */ +extern int mit_des3_key_sched + (mit_des3_cblock key, + mit_des3_key_schedule schedule); + +/* d3_str2ky.c */ +extern krb5_error_code mit_des3_string_to_key + (const krb5_encrypt_block * eblock, + krb5_keyblock * keyblock, + const krb5_data * data, + const krb5_data * salt); + +/* u_nfold.c */ +extern krb5_error_code mit_des_n_fold + (const krb5_octet * input, + const size_t in_len, + krb5_octet * output, + const size_t out_len); + +/* u_rn_key.c */ +extern int mit_des_is_weak_keyblock + (krb5_keyblock *keyblock); + +extern void mit_des_fixup_keyblock_parity + (krb5_keyblock *keyblock); + +extern krb5_error_code mit_des_set_random_generator_seed + (const krb5_data * seed, + krb5_pointer random_state); + +extern krb5_error_code mit_des_set_random_sequence_number + (const krb5_data * sequence, + krb5_pointer random_state); +#endif /*DES_INTERNAL_DEFS*/ diff --git a/src/lib/crypto/openssl/des/f_aead.c b/src/lib/crypto/openssl/des/f_aead.c new file mode 100644 index 0000000000..2046475901 --- /dev/null +++ b/src/lib/crypto/openssl/des/f_aead.c @@ -0,0 +1,33 @@ +/* lib/crypto/openssl/des/f_aead.c + * + * Copyright 2009 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + */ + +#include "des_int.h" +#include "aead.h" + + +void +krb5int_des_cbc_encrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec) +{ + /* Unsupported operation */ + abort(); +} + +void +krb5int_des_cbc_decrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock iv) +{ + /* Unsupported operation */ + abort(); +} + + diff --git a/src/lib/crypto/openssl/des/f_cbc.c b/src/lib/crypto/openssl/des/f_cbc.c new file mode 100644 index 0000000000..55b648fc13 --- /dev/null +++ b/src/lib/crypto/openssl/des/f_cbc.c @@ -0,0 +1,89 @@ +/* + * lib/crypto/openssldes/f_cbc.c + * + * Copyright (C) 1990 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * DES implementation donated by Dennis Ferguson + */ + +/* + * des_cbc_encrypt.c - an implementation of the DES cipher function in cbc mode + */ +#include "des_int.h" + +/* + * des_cbc_encrypt - {en,de}crypt a stream in CBC mode + */ + +/* + * This routine performs DES cipher-block-chaining operation, either + * encrypting from cleartext to ciphertext, if encrypt != 0 or + * decrypting from ciphertext to cleartext, if encrypt == 0. + * + * The key schedule is passed as an arg, as well as the cleartext or + * ciphertext. The cleartext and ciphertext should be in host order. + * + * NOTE-- the output is ALWAYS an multiple of 8 bytes long. If not + * enough space was provided, your program will get trashed. + * + * For encryption, the cleartext string is null padded, at the end, to + * an integral multiple of eight bytes. + * + * For decryption, the ciphertext will be used in integral multiples + * of 8 bytes, but only the first "length" bytes returned into the + * cleartext. + */ + +const mit_des_cblock mit_des_zeroblock /* = all zero */; + +#undef mit_des_cbc_encrypt +int +mit_des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out, + unsigned long length, const mit_des_key_schedule schedule, + const mit_des_cblock ivec, int enc) +{ + /* Unsupported operation */ + return KRB5_CRYPTO_INTERNAL; +} +void +krb5int_des_cbc_encrypt(const mit_des_cblock *in, + mit_des_cblock *out, + unsigned long length, + const mit_des_key_schedule schedule, + const mit_des_cblock ivec) +{ + /* Unsupported operation */ + abort(); +} + +void +krb5int_des_cbc_decrypt(const mit_des_cblock *in, + mit_des_cblock *out, + unsigned long length, + const mit_des_key_schedule schedule, + const mit_des_cblock ivec) +{ + /* Unsupported operation */ + abort(); +} + diff --git a/src/lib/crypto/openssl/des/f_cksum.c b/src/lib/crypto/openssl/des/f_cksum.c new file mode 100644 index 0000000000..c49c8fdb3f --- /dev/null +++ b/src/lib/crypto/openssl/des/f_cksum.c @@ -0,0 +1,18 @@ +/* + * lib/crypto/openssl/des/f_cksum.c + * + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + */ + +#include "des_int.h" + +unsigned long +mit_des_cbc_cksum(const krb5_octet *in, krb5_octet *out, + unsigned long length, const mit_des_key_schedule schedule, + const krb5_octet *ivec) +{ + /* Unsupported operation */ + return KRB5_CRYPTO_INTERNAL; +} + diff --git a/src/lib/crypto/openssl/des/f_parity.c b/src/lib/crypto/openssl/des/f_parity.c new file mode 100644 index 0000000000..1a83db6ef5 --- /dev/null +++ b/src/lib/crypto/openssl/des/f_parity.c @@ -0,0 +1,29 @@ +/* + * lib/crypto/openssl/des/f_parity.c + * + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + */ + +#include "des_int.h" +#include + +void +mit_des_fixup_key_parity(mit_des_cblock key) +{ + DES_set_odd_parity(key); +} + +/* + * des_check_key_parity: returns true iff key has the correct des parity. + * See des_fix_key_parity for the definition of + * correct des parity. + */ +int +mit_des_check_key_parity(mit_des_cblock key) +{ + if (!DES_check_key_parity(key)) + return(0); + return (1); +} + diff --git a/src/lib/crypto/openssl/des/f_sched.c b/src/lib/crypto/openssl/des/f_sched.c new file mode 100644 index 0000000000..e833132bfe --- /dev/null +++ b/src/lib/crypto/openssl/des/f_sched.c @@ -0,0 +1,15 @@ +/* + * lib/crypto/openssl/des/f_sched.c + * + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + */ + +#include "des_int.h" + +int +mit_des_make_key_sched(mit_des_cblock key, mit_des_key_schedule schedule) +{ + return KRB5_CRYPTO_INTERNAL; // CRYPTO_UNSOPPERTED_OP +} + diff --git a/src/lib/crypto/openssl/des/f_tables.c b/src/lib/crypto/openssl/des/f_tables.c new file mode 100644 index 0000000000..a8d161d5c6 --- /dev/null +++ b/src/lib/crypto/openssl/des/f_tables.c @@ -0,0 +1,17 @@ +/* + * lib/crypto/openssl/des/f_tables.c + * + * Copyright 2009 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + */ + +#include "des_int.h" +#include "f_tables.h" + +const unsigned DES_INT32 des_IP_table[] = {}; +const unsigned DES_INT32 des_FP_table[] = {}; +const unsigned DES_INT32 des_SP_table[] = {}; + + diff --git a/src/lib/crypto/openssl/des/f_tables.h b/src/lib/crypto/openssl/des/f_tables.h new file mode 100644 index 0000000000..af20cd59ea --- /dev/null +++ b/src/lib/crypto/openssl/des/f_tables.h @@ -0,0 +1,9 @@ +/* + * lib/crypto/des/f_tables.h + * + * Copyright 2009 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + */ + diff --git a/src/lib/crypto/openssl/des/key_sched.c b/src/lib/crypto/openssl/des/key_sched.c new file mode 100644 index 0000000000..1007ec9615 --- /dev/null +++ b/src/lib/crypto/openssl/des/key_sched.c @@ -0,0 +1,18 @@ +/* + * lib/crypto/openssl/des/key_sched.c + * + * Copyright 2009 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + */ + +#include "des_int.h" + +int +mit_des_key_sched(mit_des_cblock k, mit_des_key_schedule schedule) +{ + /* Unsupported operation */ + return KRB5_CRYPTO_INTERNAL; +} + diff --git a/src/lib/crypto/openssl/des/string2key.c b/src/lib/crypto/openssl/des/string2key.c new file mode 100644 index 0000000000..775a15364e --- /dev/null +++ b/src/lib/crypto/openssl/des/string2key.c @@ -0,0 +1,26 @@ +/* + * lib/crypto/openssl/des/string2key.c + * + * Copyright 2009 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + */ + +#include "des_int.h" +#include + + +krb5_error_code +mit_des_string_to_key_int (krb5_keyblock *key, + const krb5_data *pw, const krb5_data *salt) +{ + DES_cblock outkey; + DES_string_to_key(pw->data, &outkey); + if ( key->length < sizeof(outkey)) + return KRB5_CRYPTO_INTERNAL; + key->length = sizeof(outkey); + memcpy(key->contents, outkey, key->length); + return 0; +} + diff --git a/src/lib/crypto/openssl/des/weak_key.c b/src/lib/crypto/openssl/des/weak_key.c new file mode 100644 index 0000000000..7f97083922 --- /dev/null +++ b/src/lib/crypto/openssl/des/weak_key.c @@ -0,0 +1,87 @@ +/* + * lib/crypto/openssl/des/weak_key.c + * + * Copyright 1989,1990,2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * Under U.S. law, this software may not be exported outside the US + * without license from the U.S. Commerce department. + * + * These routines form the library interface to the DES facilities. + * + * Originally written 8/85 by Steve Miller, MIT Project Athena. + */ + +#include "des_int.h" + +/* + * The following are the weak DES keys: + */ +static const mit_des_cblock weak[16] = { + /* weak keys */ + {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, + {0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe}, + {0x1f,0x1f,0x1f,0x1f,0x0e,0x0e,0x0e,0x0e}, + {0xe0,0xe0,0xe0,0xe0,0xf1,0xf1,0xf1,0xf1}, + + /* semi-weak */ + {0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe}, + {0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01}, + + {0x1f,0xe0,0x1f,0xe0,0x0e,0xf1,0x0e,0xf1}, + {0xe0,0x1f,0xe0,0x1f,0xf1,0x0e,0xf1,0x0e}, + + {0x01,0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1}, + {0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1,0x01}, + + {0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e,0xfe}, + {0xfe,0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e}, + + {0x01,0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e}, + {0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e,0x01}, + + {0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1,0xfe}, + {0xfe,0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1} +}; + +/* + * mit_des_is_weak_key: returns true iff key is a [semi-]weak des key. + * + * Requires: key has correct odd parity. + */ +int +mit_des_is_weak_key(mit_des_cblock key) +{ + unsigned int i; + const mit_des_cblock *weak_p = weak; + + for (i = 0; i < (sizeof(weak)/sizeof(mit_des_cblock)); i++) { + if (!memcmp(weak_p++,key,sizeof(mit_des_cblock))) + return 1; + } + if ( DES_is_weak_key(key) == 1) /* Also OpenSSL's check */ + return 1; + + return 0; +} + diff --git a/src/lib/crypto/openssl/enc_provider/aes.c b/src/lib/crypto/openssl/enc_provider/aes.c new file mode 100644 index 0000000000..c1678184ba --- /dev/null +++ b/src/lib/crypto/openssl/enc_provider/aes.c @@ -0,0 +1,505 @@ +/* + * lib/crypto/openssl/enc_provider/aes.c + * + * Copyright (C) 2003, 2007, 2008, 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "enc_provider.h" +#include "aes.h" +#include +#include +#include +#include +#include +#include + +/* proto's */ +static krb5_error_code +cts_enc(const krb5_keyblock *key, const krb5_data *ivec, + const krb5_data *input, krb5_data *output); +static krb5_error_code +cbc_enc(const krb5_keyblock *key, const krb5_data *ivec, + const krb5_data *input, krb5_data *output); +static krb5_error_code +cts_decr(const krb5_keyblock *key, const krb5_data *ivec, + const krb5_data *input, krb5_data *output); +static krb5_error_code +cbc_decr(const krb5_keyblock *key, const krb5_data *ivec, + const krb5_data *input, krb5_data *output); + +static const EVP_CIPHER * +map_mode( unsigned int len) +{ + if (len==16) + return EVP_aes_128_cbc(); + if (len==32) + return EVP_aes_256_cbc(); + else + return NULL; +} + +static inline void enc(char *out, const char *in, aes_ctx *ctx) +{ + if (aes_enc_blk((const unsigned char *)in, (unsigned char *)out, ctx) + != aes_good) + abort(); +} +static inline void dec(char *out, const char *in, aes_ctx *ctx) +{ + if (aes_dec_blk((const unsigned char *)in, (unsigned char *)out, ctx) + != aes_good) + abort(); +} +static void xorblock(char *out, const char *in) +{ + int z; + for (z = 0; z < BLOCK_SIZE; z++) + out[z] ^= in[z]; +} + + +static krb5_error_code +cbc_enc(const krb5_keyblock *key, const krb5_data *ivec, + const krb5_data *input, krb5_data *output) +{ + EVP_CIPHER_CTX ciph_ctx; + unsigned char *key_buf = NULL; + unsigned char *tmp_buf = NULL; + int ret = 0, tmp_len = 0; + + key_buf = OPENSSL_malloc(key->length); + if (!key_buf) + return ENOMEM; + tmp_len = input->length; + tmp_buf = OPENSSL_malloc(input->length); + if (!tmp_buf){ + OPENSSL_free(key_buf); + return ENOMEM; + } + memcpy(key_buf, key->contents, key->length); + + EVP_CIPHER_CTX_init(&ciph_ctx); + + if (ivec && ivec->data && (ivec->length <= EVP_MAX_IV_LENGTH)){ + ret = EVP_EncryptInit_ex(&ciph_ctx, map_mode(key->length), + NULL, key_buf, (unsigned char*)ivec->data); + } else { + ret = EVP_EncryptInit_ex(&ciph_ctx, map_mode(key->length), + NULL, key_buf, NULL); + } + + if (ret == 1){ + EVP_CIPHER_CTX_set_padding(&ciph_ctx,0); + ret = EVP_EncryptUpdate(&ciph_ctx, tmp_buf, &tmp_len, + (unsigned char *)input->data, input->length); + + output->length = tmp_len; + if(ret) + ret = EVP_EncryptFinal_ex(&ciph_ctx,tmp_buf+tmp_len,&tmp_len); + } + + EVP_CIPHER_CTX_cleanup(&ciph_ctx); + + if (ret == 1){ + memcpy(output->data, tmp_buf, output->length); + ret = 0; + } else { + ret = KRB5_CRYPTO_INTERNAL; + } + + OPENSSL_free(key_buf); + OPENSSL_free(tmp_buf); + + return ret; +} + +static krb5_error_code +cbc_decr(const krb5_keyblock *key, const krb5_data *ivec, + const krb5_data *input, krb5_data *output) +{ + int ret = 0; + int tmp_len = 0; + unsigned char *key_buf = NULL; + unsigned char *tmp_buf = NULL; + EVP_CIPHER_CTX ciph_ctx; + + + key_buf = OPENSSL_malloc(key->length); + if (!key_buf) + return ENOMEM; + tmp_len = input->length; + tmp_buf = OPENSSL_malloc(input->length); + if (!tmp_buf){ + OPENSSL_free(key_buf); + return ENOMEM; + } + memcpy(key_buf, key->contents, key->length); + + EVP_CIPHER_CTX_init(&ciph_ctx); + + if (ivec && ivec->data && (ivec->length <= EVP_MAX_IV_LENGTH)) { + ret = EVP_DecryptInit_ex(&ciph_ctx, map_mode(key->length), + NULL, key_buf, (unsigned char*)ivec->data); + } else + ret = EVP_DecryptInit_ex(&ciph_ctx, map_mode(key->length), + NULL, key_buf, NULL); + + if (ret == 1) { + EVP_CIPHER_CTX_set_padding(&ciph_ctx,0); + ret = EVP_EncryptUpdate(&ciph_ctx, tmp_buf, &tmp_len, + (unsigned char *)input->data, input->length); + output->length = tmp_len; + if (ret == 1) + ret = EVP_DecryptFinal_ex(&ciph_ctx,tmp_buf+tmp_len,&tmp_len); + } + + EVP_CIPHER_CTX_cleanup(&ciph_ctx); + + if (ret == 1) { + output->length += tmp_len; + memcpy(output->data, tmp_buf, output->length); + ret = 0; + } else { + ret = KRB5_CRYPTO_INTERNAL; + } + + OPENSSL_free(key_buf); + OPENSSL_free(tmp_buf); + + return ret; +} + +static krb5_error_code +cts_enc(const krb5_keyblock *key, const krb5_data *ivec, + const krb5_data *input, krb5_data *output) +{ + size_t size = 0; + int ret = 0, tmp_len = 0; + unsigned char iv_cts[EVP_MAX_IV_LENGTH*4]; + unsigned char *tmp_buf = NULL; + AES_KEY enck; + + memset(iv_cts,0,sizeof(iv_cts)); + if (ivec && ivec->data && (ivec->length <= sizeof(iv_cts))) + memcpy(iv_cts, ivec->data,ivec->length); + + tmp_buf = OPENSSL_malloc(input->length); + if (!tmp_buf) + return ENOMEM; + tmp_len = input->length; + + AES_set_encrypt_key(key->contents, 8*key->length, &enck); + + size = CRYPTO_cts128_encrypt((unsigned char *)input->data, tmp_buf, + input->length, &enck, + iv_cts, (cbc128_f)AES_cbc_encrypt); + + if (size <= 0 || output->length < size) { + ret = KRB5_CRYPTO_INTERNAL; + } else { + output->length = size; + memcpy(output->data, tmp_buf, output->length); + ret = 0; + } + + OPENSSL_free(tmp_buf); + + return ret; +} + +static krb5_error_code +cts_decr(const krb5_keyblock *key, const krb5_data *ivec, + const krb5_data *input, krb5_data *output) +{ + size_t size = 0; + int ret = 0, tmp_len = 0; + unsigned char iv_cts[EVP_MAX_IV_LENGTH*4]; + unsigned char *tmp_buf = NULL; + AES_KEY deck; + + memset(iv_cts,0,EVP_MAX_IV_LENGTH*4); + if (ivec && ivec->data && (ivec->length <= EVP_MAX_IV_LENGTH)) + memcpy(iv_cts, ivec->data,ivec->length); + + tmp_buf = OPENSSL_malloc(input->length); + if (!tmp_buf) + return ENOMEM; + tmp_len = input->length; + + AES_set_decrypt_key(key->contents, 8*key->length, &deck); + + size = CRYPTO_cts128_decrypt((unsigned char *)input->data, tmp_buf, + input->length, &deck, + iv_cts, (cbc128_f)AES_cbc_encrypt); + + + if (size <= 0 || output->length < size) { + ret = KRB5_CRYPTO_INTERNAL; + } else { + output->length = size + 16; + memcpy(output->data, tmp_buf, output->length); + ret = 0; + } + + OPENSSL_free(tmp_buf); + + return ret; +} + +krb5_error_code +krb5int_aes_encrypt(const krb5_keyblock *key, const krb5_data *ivec, + const krb5_data *input, krb5_data *output) +{ + int ret = 0; + + if ( input->length < BLOCK_SIZE * 2) { + + ret = cbc_enc(key, ivec, input, output); + + } else { + + ret = cts_enc(key, ivec, input, output); + } + + return ret; +} + +krb5_error_code +krb5int_aes_decrypt(const krb5_keyblock *key, const krb5_data *ivec, + const krb5_data *input, krb5_data *output) +{ + int ret = 0; + + if ( input->length < BLOCK_SIZE*2) { + + ret = cbc_decr(key, ivec, input, output); + + } else { + + ret = cts_decr(key, ivec, input, output); + + } + + return ret; +} + +static krb5_error_code +krb5int_aes_encrypt_iov(const krb5_keyblock *key, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + aes_ctx ctx; + char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE]; + int nblocks = 0, blockno; + size_t input_length, i; + + if (aes_enc_key(key->contents, key->length, &ctx) != aes_good) + abort(); + + if (ivec != NULL) + memcpy(tmp, ivec->data, BLOCK_SIZE); + else + memset(tmp, 0, BLOCK_SIZE); + + for (i = 0, input_length = 0; i < num_data; i++) { + krb5_crypto_iov *iov = &data[i]; + + if (ENCRYPT_IOV(iov)) + input_length += iov->data.length; + } + + nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE; + + assert(nblocks > 1); + + { + char blockN2[BLOCK_SIZE]; /* second last */ + char blockN1[BLOCK_SIZE]; /* last block */ + struct iov_block_state input_pos, output_pos; + + IOV_BLOCK_STATE_INIT(&input_pos); + IOV_BLOCK_STATE_INIT(&output_pos); + + for (blockno = 0; blockno < nblocks - 2; blockno++) { + char blockN[BLOCK_SIZE]; + + krb5int_c_iov_get_block((unsigned char *)blockN, BLOCK_SIZE, data, num_data, &input_pos); + xorblock(tmp, blockN); + enc(tmp2, tmp, &ctx); + krb5int_c_iov_put_block(data, num_data, (unsigned char *)tmp2, BLOCK_SIZE, &output_pos); + + /* Set up for next block. */ + memcpy(tmp, tmp2, BLOCK_SIZE); + } + + /* Do final CTS step for last two blocks (the second of which + may or may not be incomplete). */ + + /* First, get the last two blocks */ + memset(blockN1, 0, sizeof(blockN1)); /* pad last block with zeros */ + krb5int_c_iov_get_block((unsigned char *)blockN2, BLOCK_SIZE, data, num_data, &input_pos); + krb5int_c_iov_get_block((unsigned char *)blockN1, BLOCK_SIZE, data, num_data, &input_pos); + + /* Encrypt second last block */ + xorblock(tmp, blockN2); + enc(tmp2, tmp, &ctx); + memcpy(blockN2, tmp2, BLOCK_SIZE); /* blockN2 now contains first block */ + memcpy(tmp, tmp2, BLOCK_SIZE); + + /* Encrypt last block */ + xorblock(tmp, blockN1); + enc(tmp2, tmp, &ctx); + memcpy(blockN1, tmp2, BLOCK_SIZE); + + /* Put the last two blocks back into the iovec (reverse order) */ + krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN1, BLOCK_SIZE, &output_pos); + krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN2, BLOCK_SIZE, &output_pos); + + if (ivec != NULL) + memcpy(ivec->data, blockN1, BLOCK_SIZE); + } + + return 0; +} + +static krb5_error_code +krb5int_aes_decrypt_iov(const krb5_keyblock *key, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + aes_ctx ctx; + char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE], tmp3[BLOCK_SIZE]; + int nblocks = 0, blockno; + unsigned int i; + size_t input_length; + + if (aes_dec_key(key->contents, key->length, &ctx) != aes_good) + abort(); + + if (ivec != NULL) + memcpy(tmp, ivec->data, BLOCK_SIZE); + else + memset(tmp, 0, BLOCK_SIZE); + + for (i = 0, input_length = 0; i < num_data; i++) { + krb5_crypto_iov *iov = &data[i]; + + if (ENCRYPT_IOV(iov)) + input_length += iov->data.length; + } + + nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE; + + assert(nblocks > 1); + + { + char blockN2[BLOCK_SIZE]; /* second last */ + char blockN1[BLOCK_SIZE]; /* last block */ + struct iov_block_state input_pos, output_pos; + + IOV_BLOCK_STATE_INIT(&input_pos); + IOV_BLOCK_STATE_INIT(&output_pos); + + for (blockno = 0; blockno < nblocks - 2; blockno++) { + char blockN[BLOCK_SIZE]; + + krb5int_c_iov_get_block((unsigned char *)blockN, BLOCK_SIZE, data, num_data, &input_pos); + dec(tmp2, blockN, &ctx); + xorblock(tmp2, tmp); + krb5int_c_iov_put_block(data, num_data, (unsigned char *)tmp2, BLOCK_SIZE, &output_pos); + memcpy(tmp, blockN, BLOCK_SIZE); + } + + /* Do last two blocks, the second of which (next-to-last block + of plaintext) may be incomplete. */ + + /* First, get the last two encrypted blocks */ + memset(blockN1, 0, sizeof(blockN1)); /* pad last block with zeros */ + krb5int_c_iov_get_block((unsigned char *)blockN2, BLOCK_SIZE, data, num_data, &input_pos); + krb5int_c_iov_get_block((unsigned char *)blockN1, BLOCK_SIZE, data, num_data, &input_pos); + + /* Decrypt second last block */ + dec(tmp2, blockN2, &ctx); + /* Set tmp2 to last (possibly partial) plaintext block, and + save it. */ + xorblock(tmp2, blockN1); + memcpy(blockN2, tmp2, BLOCK_SIZE); + + /* Maybe keep the trailing part, and copy in the last + ciphertext block. */ + input_length %= BLOCK_SIZE; + memcpy(tmp2, blockN1, input_length ? input_length : BLOCK_SIZE); + dec(tmp3, tmp2, &ctx); + xorblock(tmp3, tmp); + /* Copy out ivec first before we clobber blockN1 with plaintext */ + if (ivec != NULL) + memcpy(ivec->data, blockN1, BLOCK_SIZE); + memcpy(blockN1, tmp3, BLOCK_SIZE); + + /* Put the last two blocks back into the iovec */ + krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN1, BLOCK_SIZE, &output_pos); + krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN2, BLOCK_SIZE, &output_pos); + } + + return 0; +} + +static krb5_error_code +krb5int_aes_init_state (const krb5_keyblock *key, krb5_keyusage usage, + krb5_data *state) +{ + state->length = 16; + state->data = (void *) malloc(16); + if (state->data == NULL) + return ENOMEM; + memset(state->data, 0, state->length); + return 0; +} + +const struct krb5_enc_provider krb5int_enc_aes128 = { + 16, + 16, 16, + krb5int_aes_encrypt, + krb5int_aes_decrypt, + krb5int_aes_make_key, + krb5int_aes_init_state, + krb5int_default_free_state, + krb5int_aes_encrypt_iov, + krb5int_aes_decrypt_iov +}; + +const struct krb5_enc_provider krb5int_enc_aes256 = { + 16, + 32, 32, + krb5int_aes_encrypt, + krb5int_aes_decrypt, + krb5int_aes_make_key, + krb5int_aes_init_state, + krb5int_default_free_state, + krb5int_aes_encrypt_iov, + krb5int_aes_decrypt_iov +}; + diff --git a/src/lib/crypto/openssl/enc_provider/des.c b/src/lib/crypto/openssl/enc_provider/des.c index b7a05db7c3..4965c6e6fa 100644 --- a/src/lib/crypto/openssl/enc_provider/des.c +++ b/src/lib/crypto/openssl/enc_provider/des.c @@ -35,7 +35,6 @@ validate_iov(const krb5_keyblock *key, const krb5_data *ivec, for (i = 0, input_length = 0; i < num_data; i++) { const krb5_crypto_iov *iov = &data[i]; - if (ENCRYPT_IOV(iov)) input_length += iov->data.length; } @@ -54,12 +53,11 @@ static krb5_error_code k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { - int ret = 0, tmp_len = 0; - unsigned int tmp_buf_len = 0; + int ret = 0, tmp_len = 0; + unsigned int tmp_buf_len = 0; unsigned char *keybuf = NULL; unsigned char *tmp_buf = NULL; - unsigned char iv[EVP_MAX_IV_LENGTH]; - EVP_CIPHER_CTX ciph_ctx; + EVP_CIPHER_CTX ciph_ctx; ret = validate(key, ivec, input, output); if (ret) @@ -68,11 +66,6 @@ k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec, keybuf=key->contents; keybuf[key->length] = '\0'; - if ( ivec && ivec->data ) { - memset(iv,0,sizeof(iv)); - memcpy(iv,ivec->data,ivec->length); - } - tmp_buf_len = output->length*2; tmp_buf=OPENSSL_malloc(tmp_buf_len); if (!tmp_buf) @@ -82,13 +75,13 @@ k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec, EVP_CIPHER_CTX_init(&ciph_ctx); ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL, keybuf, - (ivec && ivec->data) ? iv : NULL); + (ivec) ? (unsigned char*)ivec->data : NULL); if (ret) { EVP_CIPHER_CTX_set_padding(&ciph_ctx,0); ret = EVP_EncryptUpdate(&ciph_ctx, tmp_buf, &tmp_len, (unsigned char *)input->data, input->length); if (!ret || output->length < (unsigned int)tmp_len) { - return KRB5_CRYPTO_INTERNAL; + ret = KRB5_CRYPTO_INTERNAL; } else { output->length = tmp_len; ret = EVP_EncryptFinal_ex(&ciph_ctx, tmp_buf + tmp_len, &tmp_len); @@ -97,13 +90,13 @@ k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec, EVP_CIPHER_CTX_cleanup(&ciph_ctx); - if (ret) + if (ret == 1) memcpy(output->data,tmp_buf, output->length); memset(tmp_buf, 0, tmp_buf_len); OPENSSL_free(tmp_buf); - if (!ret) + if (ret != 1) return KRB5_CRYPTO_INTERNAL; return 0; } @@ -114,10 +107,9 @@ k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { /* key->enctype was checked by the caller */ - int ret = 0, tmp_len = 0; + int ret = 0, tmp_len = 0; unsigned char *keybuf = NULL; unsigned char *tmp_buf; - unsigned char iv[EVP_MAX_IV_LENGTH]; EVP_CIPHER_CTX ciph_ctx; ret = validate(key, ivec, input, output); @@ -127,10 +119,6 @@ k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec, keybuf=key->contents; keybuf[key->length] = '\0'; - if ( ivec != NULL && ivec->data ){ - memset(iv,0,sizeof(iv)); - memcpy(iv,ivec->data,ivec->length); - } tmp_buf=OPENSSL_malloc(output->length); if (!tmp_buf) return ENOMEM; @@ -139,7 +127,7 @@ k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec, EVP_CIPHER_CTX_init(&ciph_ctx); ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL, keybuf, - (ivec && ivec->data) ? iv : NULL); + (ivec) ? (unsigned char*)ivec->data : NULL); if (ret) { EVP_CIPHER_CTX_set_padding(&ciph_ctx,0); ret = EVP_DecryptUpdate(&ciph_ctx, tmp_buf, &tmp_len, @@ -152,13 +140,13 @@ k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec, EVP_CIPHER_CTX_cleanup(&ciph_ctx); - if (ret) + if (ret == 1) memcpy(output->data,tmp_buf, output->length); memset(tmp_buf,0,output->length); OPENSSL_free(tmp_buf); - if (!ret) + if ( ret != 1) return KRB5_CRYPTO_INTERNAL; return 0; } @@ -169,21 +157,21 @@ k5_des_encrypt_iov(const krb5_keyblock *key, krb5_crypto_iov *data, size_t num_data) { - int ret = 0, tmp_len = MIT_DES_BLOCK_LENGTH; - EVP_CIPHER_CTX ciph_ctx; - unsigned char *keybuf = NULL ; - unsigned char iv[EVP_MAX_IV_LENGTH]; - + int ret = 0, tmp_len = MIT_DES_BLOCK_LENGTH; + int oblock_len = MIT_DES_BLOCK_LENGTH * num_data; + unsigned char *iblock = NULL, *oblock = NULL; + unsigned char *keybuf = NULL ; struct iov_block_state input_pos, output_pos; - int oblock_len = MIT_DES_BLOCK_LENGTH*num_data; - unsigned char *iblock, *oblock; + EVP_CIPHER_CTX ciph_ctx; iblock = OPENSSL_malloc(MIT_DES_BLOCK_LENGTH); if (!iblock) return ENOMEM; oblock = OPENSSL_malloc(oblock_len); - if (!oblock) + if (!oblock){ + OPENSSL_free(iblock); return ENOMEM; + } IOV_BLOCK_STATE_INIT(&input_pos); IOV_BLOCK_STATE_INIT(&output_pos); @@ -195,19 +183,18 @@ k5_des_encrypt_iov(const krb5_keyblock *key, if (ret) return ret; - if (ivec && ivec->data){ - memset(iv,0,sizeof(iv)); - memcpy(iv,ivec->data,ivec->length); - } - memset(oblock, 0, oblock_len); EVP_CIPHER_CTX_init(&ciph_ctx); ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL, - keybuf, (ivec && ivec->data) ? iv : NULL); - if (!ret) + keybuf, (ivec && ivec->data) ? (unsigned char*)ivec->data : NULL); + if (!ret){ + EVP_CIPHER_CTX_cleanup(&ciph_ctx); + OPENSSL_free(iblock); + OPENSSL_free(oblock); return KRB5_CRYPTO_INTERNAL; + } EVP_CIPHER_CTX_set_padding(&ciph_ctx,0); @@ -229,11 +216,6 @@ k5_des_encrypt_iov(const krb5_keyblock *key, if(ret) ret = EVP_EncryptFinal_ex(&ciph_ctx, oblock+16, &tmp_len); - if (ret) { - if (ivec != NULL) - memcpy(iv, oblock, MIT_DES_BLOCK_LENGTH); - } - EVP_CIPHER_CTX_cleanup(&ciph_ctx); memset(iblock,0,sizeof(iblock)); @@ -241,7 +223,7 @@ k5_des_encrypt_iov(const krb5_keyblock *key, OPENSSL_free(iblock); OPENSSL_free(oblock); - if (!ret) + if ( ret != 1) return KRB5_CRYPTO_INTERNAL; return 0; } @@ -252,21 +234,22 @@ k5_des_decrypt_iov(const krb5_keyblock *key, krb5_crypto_iov *data, size_t num_data) { - int ret = 0, tmp_len = MIT_DES_BLOCK_LENGTH; - EVP_CIPHER_CTX ciph_ctx; - unsigned char *keybuf = NULL ; - unsigned char iv[EVP_MAX_IV_LENGTH]; - + int ret = 0; + int tmp_len = MIT_DES_BLOCK_LENGTH; + int oblock_len = MIT_DES_BLOCK_LENGTH*num_data; + unsigned char *iblock = NULL, *oblock = NULL; + unsigned char *keybuf = NULL; struct iov_block_state input_pos, output_pos; - int oblock_len = MIT_DES_BLOCK_LENGTH*num_data; - unsigned char *iblock, *oblock; + EVP_CIPHER_CTX ciph_ctx; iblock = OPENSSL_malloc(MIT_DES_BLOCK_LENGTH); if (!iblock) return ENOMEM; oblock = OPENSSL_malloc(oblock_len); - if (!oblock) + if (!oblock){ + OPENSSL_free(iblock); return ENOMEM; + } IOV_BLOCK_STATE_INIT(&input_pos); IOV_BLOCK_STATE_INIT(&output_pos); @@ -278,19 +261,18 @@ k5_des_decrypt_iov(const krb5_keyblock *key, if (ret) return ret; - if (ivec && ivec->data){ - memset(iv,0,sizeof(iv)); - memcpy(iv,ivec->data,ivec->length); - } - memset(oblock, 0, oblock_len); EVP_CIPHER_CTX_init(&ciph_ctx); ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL, - keybuf, (ivec && ivec->data) ? iv : NULL); - if (!ret) + keybuf, (ivec) ? (unsigned char*)ivec->data : NULL); + if (!ret){ + EVP_CIPHER_CTX_cleanup(&ciph_ctx); + OPENSSL_free(iblock); + OPENSSL_free(oblock); return KRB5_CRYPTO_INTERNAL; + } EVP_CIPHER_CTX_set_padding(&ciph_ctx,0); @@ -315,11 +297,6 @@ k5_des_decrypt_iov(const krb5_keyblock *key, if(ret) ret = EVP_DecryptFinal_ex(&ciph_ctx, oblock+16, &tmp_len); - if (ret) { - if (ivec != NULL) - memcpy(iv, oblock, MIT_DES_BLOCK_LENGTH); - } - EVP_CIPHER_CTX_cleanup(&ciph_ctx); memset(iblock,0,sizeof(iblock)); @@ -327,7 +304,7 @@ k5_des_decrypt_iov(const krb5_keyblock *key, OPENSSL_free(iblock); OPENSSL_free(oblock); - if (!ret) + if (ret != 1) return KRB5_CRYPTO_INTERNAL; return 0; } diff --git a/src/lib/crypto/openssl/enc_provider/des3.c b/src/lib/crypto/openssl/enc_provider/des3.c index 4445af0d8f..1dec8e27e2 100644 --- a/src/lib/crypto/openssl/enc_provider/des3.c +++ b/src/lib/crypto/openssl/enc_provider/des3.c @@ -36,7 +36,6 @@ validate_iov(const krb5_keyblock *key, const krb5_data *ivec, for (i = 0, input_length = 0; i < num_data; i++) { const krb5_crypto_iov *iov = &data[i]; - if (ENCRYPT_IOV(iov)) input_length += iov->data.length; } @@ -55,12 +54,11 @@ static krb5_error_code k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { - int ret = 0, tmp_len = 0; - unsigned int tmp_buf_len = 0; + int ret = 0, tmp_len = 0; + unsigned int tmp_buf_len = 0; unsigned char *keybuf = NULL; unsigned char *tmp_buf = NULL; - unsigned char iv[EVP_MAX_IV_LENGTH]; - EVP_CIPHER_CTX ciph_ctx; + EVP_CIPHER_CTX ciph_ctx; ret = validate(key, ivec, input, output); if (ret) @@ -69,9 +67,6 @@ k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec, keybuf=key->contents; keybuf[key->length] = '\0'; - if (ivec && ivec->data) { - memcpy(iv,ivec->data,ivec->length); - } tmp_buf_len = output->length * 2; tmp_buf = OPENSSL_malloc(tmp_buf_len); if (!tmp_buf) @@ -80,7 +75,7 @@ k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec, EVP_CIPHER_CTX_init(&ciph_ctx); ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL, keybuf, - (ivec && ivec->data) ? iv : NULL); + (ivec) ? (unsigned char*)ivec->data : NULL); if (ret) { EVP_CIPHER_CTX_set_padding(&ciph_ctx,0); ret = EVP_EncryptUpdate(&ciph_ctx, tmp_buf, &tmp_len, @@ -95,12 +90,13 @@ k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec, EVP_CIPHER_CTX_cleanup(&ciph_ctx); - if (ret) + if (ret == 1) memcpy(output->data,tmp_buf, output->length); + memset(tmp_buf, 0, tmp_buf_len); OPENSSL_free(tmp_buf); - if (!ret) + if (ret != 1) return KRB5_CRYPTO_INTERNAL; return 0; @@ -111,11 +107,11 @@ static krb5_error_code k5_des3_decrypt(const krb5_keyblock *key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { - int ret = 0, tmp_len = 0; - EVP_CIPHER_CTX ciph_ctx; + int ret = 0, tmp_len = 0; + unsigned int tmp_buf_len = 0; unsigned char *keybuf = NULL; unsigned char *tmp_buf = NULL; - unsigned char iv[EVP_MAX_IV_LENGTH]; + EVP_CIPHER_CTX ciph_ctx; ret = validate(key, ivec, input, output); if (ret) @@ -124,24 +120,22 @@ k5_des3_decrypt(const krb5_keyblock *key, const krb5_data *ivec, keybuf=key->contents; keybuf[key->length] = '\0'; - if (ivec && ivec->data) { - memset(iv,0,sizeof(iv)); - memcpy(iv,ivec->data,ivec->length); - } - - tmp_buf=OPENSSL_malloc(output->length); + tmp_buf_len = output->length; + tmp_buf=OPENSSL_malloc(tmp_buf_len); if (!tmp_buf) return ENOMEM; EVP_CIPHER_CTX_init(&ciph_ctx); ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL, keybuf, - (ivec && ivec->data) ? iv: NULL); + (ivec) ? (unsigned char*)ivec->data: NULL); if (ret) { EVP_CIPHER_CTX_set_padding(&ciph_ctx,0); ret = EVP_DecryptUpdate(&ciph_ctx, tmp_buf, &tmp_len, (unsigned char *)input->data, input->length); - if (ret) { + if (!ret || output->length < (unsigned int)tmp_len) { + ret = KRB5_CRYPTO_INTERNAL; + } else { output->length = tmp_len; ret = EVP_DecryptFinal_ex(&ciph_ctx, tmp_buf+tmp_len, &tmp_len); } @@ -149,13 +143,13 @@ k5_des3_decrypt(const krb5_keyblock *key, const krb5_data *ivec, EVP_CIPHER_CTX_cleanup(&ciph_ctx); - if (ret) + if (ret == 1) memcpy(output->data,tmp_buf, output->length); - memset(tmp_buf,0,output->length); + memset(tmp_buf,0,tmp_buf_len); OPENSSL_free(tmp_buf); - if (!ret) + if (ret != 1) return KRB5_CRYPTO_INTERNAL; return 0; @@ -167,14 +161,13 @@ k5_des3_encrypt_iov(const krb5_keyblock *key, krb5_crypto_iov *data, size_t num_data) { - int ret = 0, tmp_len = MIT_DES_BLOCK_LENGTH; - EVP_CIPHER_CTX ciph_ctx; - unsigned char *keybuf = NULL ; - unsigned char iv[EVP_MAX_IV_LENGTH]; - + int ret = 0; + int tmp_len = MIT_DES_BLOCK_LENGTH; + int oblock_len = MIT_DES_BLOCK_LENGTH*num_data; + unsigned char *iblock = NULL, *oblock = NULL; + unsigned char *keybuf = NULL; struct iov_block_state input_pos, output_pos; - int oblock_len = MIT_DES_BLOCK_LENGTH*num_data; - unsigned char *iblock, *oblock; + EVP_CIPHER_CTX ciph_ctx; ret = validate_iov(key, ivec, data, num_data); if (ret) @@ -184,8 +177,10 @@ k5_des3_encrypt_iov(const krb5_keyblock *key, if (!iblock) return ENOMEM; oblock = OPENSSL_malloc(oblock_len); - if (!oblock) + if (!oblock){ + OPENSSL_free(iblock); return ENOMEM; + } IOV_BLOCK_STATE_INIT(&input_pos); IOV_BLOCK_STATE_INIT(&output_pos); @@ -193,19 +188,18 @@ k5_des3_encrypt_iov(const krb5_keyblock *key, keybuf=key->contents; keybuf[key->length] = '\0'; - if (ivec && ivec->data){ - memset(iv,0,sizeof(iv)); - memcpy(iv,ivec->data,ivec->length); - } - memset(oblock, 0, oblock_len); EVP_CIPHER_CTX_init(&ciph_ctx); ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL, - keybuf, (ivec && ivec->data) ? iv : NULL); - if (!ret) + keybuf, (ivec) ? (unsigned char*)ivec->data : NULL); + if (!ret){ + EVP_CIPHER_CTX_cleanup(&ciph_ctx); + OPENSSL_free(iblock); + OPENSSL_free(oblock); return KRB5_CRYPTO_INTERNAL; + } EVP_CIPHER_CTX_set_padding(&ciph_ctx,0); @@ -229,11 +223,6 @@ k5_des3_encrypt_iov(const krb5_keyblock *key, if(ret) ret = EVP_EncryptFinal_ex(&ciph_ctx, oblock+input_pos.data_pos, &tmp_len); - if (ret) { - if (ivec != NULL) - memcpy(iv, oblock, MIT_DES_BLOCK_LENGTH); - } - EVP_CIPHER_CTX_cleanup(&ciph_ctx); memset(iblock,0,sizeof(iblock)); @@ -241,7 +230,7 @@ k5_des3_encrypt_iov(const krb5_keyblock *key, OPENSSL_free(iblock); OPENSSL_free(oblock); - if (!ret) + if (ret != 1) return KRB5_CRYPTO_INTERNAL; return 0; } @@ -252,14 +241,13 @@ k5_des3_decrypt_iov(const krb5_keyblock *key, krb5_crypto_iov *data, size_t num_data) { - int ret = 0, tmp_len = MIT_DES_BLOCK_LENGTH; - EVP_CIPHER_CTX ciph_ctx; - unsigned char *keybuf = NULL ; - unsigned char iv[EVP_MAX_IV_LENGTH]; - + int ret = 0; + int tmp_len = MIT_DES_BLOCK_LENGTH; + int oblock_len = MIT_DES_BLOCK_LENGTH * num_data; + unsigned char *iblock = NULL, *oblock = NULL; + unsigned char *keybuf = NULL ; struct iov_block_state input_pos, output_pos; - int oblock_len = MIT_DES_BLOCK_LENGTH*num_data; - unsigned char *iblock, *oblock; + EVP_CIPHER_CTX ciph_ctx; ret = validate_iov(key, ivec, data, num_data); if (ret) @@ -269,8 +257,10 @@ k5_des3_decrypt_iov(const krb5_keyblock *key, if (!iblock) return ENOMEM; oblock = OPENSSL_malloc(oblock_len); - if (!oblock) + if (!oblock){ + OPENSSL_free(iblock); return ENOMEM; + } IOV_BLOCK_STATE_INIT(&input_pos); IOV_BLOCK_STATE_INIT(&output_pos); @@ -278,19 +268,18 @@ k5_des3_decrypt_iov(const krb5_keyblock *key, keybuf=key->contents; keybuf[key->length] = '\0'; - if (ivec && ivec->data){ - memset(iv,0,sizeof(iv)); - memcpy(iv,ivec->data,ivec->length); - } - memset(oblock, 0, oblock_len); EVP_CIPHER_CTX_init(&ciph_ctx); ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL, - keybuf, (ivec && ivec->data) ? iv : NULL); - if (!ret) + keybuf, (ivec) ? (unsigned char*)ivec->data : NULL); + if (!ret){ + EVP_CIPHER_CTX_cleanup(&ciph_ctx); + OPENSSL_free(iblock); + OPENSSL_free(oblock); return KRB5_CRYPTO_INTERNAL; + } EVP_CIPHER_CTX_set_padding(&ciph_ctx,0); @@ -315,11 +304,6 @@ k5_des3_decrypt_iov(const krb5_keyblock *key, ret = EVP_DecryptFinal_ex(&ciph_ctx, oblock + input_pos.data_pos, &tmp_len); - if (ret) { - if (ivec != NULL) - memcpy(iv, oblock, MIT_DES_BLOCK_LENGTH); - } - EVP_CIPHER_CTX_cleanup(&ciph_ctx); memset(iblock,0,sizeof(iblock)); @@ -327,7 +311,7 @@ k5_des3_decrypt_iov(const krb5_keyblock *key, OPENSSL_free(iblock); OPENSSL_free(oblock); - if (!ret) + if (ret != 1) return KRB5_CRYPTO_INTERNAL; return 0; } diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c index 455a47faaf..ae2f58f406 100644 --- a/src/lib/crypto/openssl/enc_provider/rc4.c +++ b/src/lib/crypto/openssl/enc_provider/rc4.c @@ -62,7 +62,7 @@ k5_arcfour_docrypt(const krb5_keyblock *key, const krb5_data *state, EVP_CIPHER_CTX_cleanup(&ciph_ctx); - if (!ret) + if (ret != 1) return KRB5_CRYPTO_INTERNAL; output->length += tmp_len; @@ -90,8 +90,10 @@ k5_arcfour_docrypt_iov(const krb5_keyblock *key, EVP_CIPHER_CTX_init(&ciph_ctx); ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_rc4(), NULL, keybuf, NULL); - if (!ret) - return -1; + if (!ret){ + EVP_CIPHER_CTX_cleanup(&ciph_ctx); + return KRB5_CRYPTO_INTERNAL; + } for (i = 0; i < num_data; i++) { iov = &data[i]; @@ -112,7 +114,7 @@ k5_arcfour_docrypt_iov(const krb5_keyblock *key, EVP_CIPHER_CTX_cleanup(&ciph_ctx); - if (!ret) + if (ret != 1) return KRB5_CRYPTO_INTERNAL; iov->data.length += tmp_len;