1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
3
* lib/crypto/old/old_aead.c
5
* Copyright 2008 by the Massachusetts Institute of Technology.
8
* Export of this software from the United States of America may
9
* require a specific license from the United States Government.
10
* It is the responsibility of any person or organization contemplating
11
* export to obtain such a license before exporting.
13
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
14
* distribute this software and its documentation for any purpose and
15
* without fee is hereby granted, provided that the above copyright
16
* notice appear in all copies and that both that copyright notice and
17
* this permission notice appear in supporting documentation, and that
18
* the name of M.I.T. not be used in advertising or publicity pertaining
19
* to distribution of the software without specific, written prior
20
* permission. Furthermore if you modify this software you must label
21
* your software as modified software and not distribute it in such a
22
* fashion that it might be confused with the original M.I.T. software.
23
* M.I.T. makes no representations about the suitability of
24
* this software for any purpose. It is provided "as is" without express
25
* or implied warranty.
34
krb5int_old_crypto_length(const struct krb5_keytypes *ktp,
38
case KRB5_CRYPTO_TYPE_HEADER:
39
return ktp->enc->block_size + ktp->hash->hashsize;
40
case KRB5_CRYPTO_TYPE_PADDING:
41
return ktp->enc->block_size;
42
case KRB5_CRYPTO_TYPE_TRAILER:
44
case KRB5_CRYPTO_TYPE_CHECKSUM:
45
return ktp->hash->hashsize;
47
assert(0 && "invalid cryptotype passed to krb5int_old_crypto_length");
53
krb5int_old_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
54
krb5_keyusage usage, const krb5_data *ivec,
55
krb5_crypto_iov *data, size_t num_data)
57
const struct krb5_enc_provider *enc = ktp->enc;
58
const struct krb5_hash_provider *hash = ktp->hash;
60
krb5_crypto_iov *header, *trailer, *padding;
61
krb5_data checksum, confounder, crcivec = empty_data();
62
unsigned int plainlen, padsize;
65
/* E(Confounder | Checksum | Plaintext | Pad) */
67
plainlen = enc->block_size + hash->hashsize;
68
for (i = 0; i < num_data; i++) {
69
krb5_crypto_iov *iov = &data[i];
71
if (iov->flags == KRB5_CRYPTO_TYPE_DATA)
72
plainlen += iov->data.length;
75
header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
77
header->data.length < enc->block_size + hash->hashsize)
78
return KRB5_BAD_MSIZE;
80
/* Trailer may be absent. */
81
trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
83
trailer->data.length = 0;
85
/* Check that the input data is correctly padded. */
86
padsize = krb5_roundup(plainlen, enc->block_size) - plainlen;
87
padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
88
if (padsize > 0 && (padding == NULL || padding->data.length < padsize))
89
return KRB5_BAD_MSIZE;
91
padding->data.length = padsize;
92
memset(padding->data.data, 0, padsize);
95
/* Generate a confounder in the header block. */
96
confounder = make_data(header->data.data, enc->block_size);
97
ret = krb5_c_random_make_octets(0, &confounder);
100
checksum = make_data(header->data.data + enc->block_size, hash->hashsize);
101
memset(checksum.data, 0, hash->hashsize);
103
/* Checksum the plaintext with zeroed checksum and padding. */
104
ret = hash->hash(data, num_data, &checksum);
108
/* Use the key as the ivec for des-cbc-crc if none was provided. */
109
if (key->keyblock.enctype == ENCTYPE_DES_CBC_CRC && ivec == NULL) {
110
ret = alloc_data(&crcivec, key->keyblock.length);
111
memcpy(crcivec.data, key->keyblock.contents, key->keyblock.length);
115
ret = enc->encrypt(key, ivec, data, num_data);
120
zapfree(crcivec.data, crcivec.length);
125
krb5int_old_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
126
krb5_keyusage usage, const krb5_data *ivec,
127
krb5_crypto_iov *data, size_t num_data)
129
const struct krb5_enc_provider *enc = ktp->enc;
130
const struct krb5_hash_provider *hash = ktp->hash;
132
krb5_crypto_iov *header, *trailer;
133
krb5_data checksum, crcivec = empty_data();
134
char *saved_checksum = NULL;
136
unsigned int cipherlen = 0;
138
/* Check that the input data is correctly padded. */
139
for (i = 0; i < num_data; i++) {
140
const krb5_crypto_iov *iov = &data[i];
142
if (ENCRYPT_IOV(iov))
143
cipherlen += iov->data.length;
145
if (cipherlen % enc->block_size != 0)
146
return KRB5_BAD_MSIZE;
148
header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
149
if (header == NULL ||
150
header->data.length != enc->block_size + hash->hashsize)
151
return KRB5_BAD_MSIZE;
153
trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
154
if (trailer != NULL && trailer->data.length != 0)
155
return KRB5_BAD_MSIZE;
157
/* Use the key as the ivec for des-cbc-crc if none was provided. */
158
if (key->keyblock.enctype == ENCTYPE_DES_CBC_CRC && ivec == NULL) {
159
ret = alloc_data(&crcivec, key->keyblock.length);
160
memcpy(crcivec.data, key->keyblock.contents, key->keyblock.length);
164
/* Decrypt the ciphertext. */
165
ret = enc->decrypt(key, ivec, data, num_data);
169
/* Save the checksum, then zero it out in the plaintext. */
170
checksum = make_data(header->data.data + enc->block_size, hash->hashsize);
171
saved_checksum = k5alloc(hash->hashsize, &ret);
172
if (saved_checksum == NULL)
174
memcpy(saved_checksum, checksum.data, checksum.length);
175
memset(checksum.data, 0, checksum.length);
178
* Checksum the plaintext (with zeroed checksum field), storing the result
179
* back into the plaintext field we just zeroed out. Then compare it to
180
* the saved checksum.
182
ret = hash->hash(data, num_data, &checksum);
183
if (memcmp(checksum.data, saved_checksum, checksum.length) != 0) {
184
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
189
zapfree(crcivec.data, crcivec.length);
190
zapfree(saved_checksum, hash->hashsize);