~ubuntu-branches/ubuntu/precise/krb5/precise-updates

« back to all changes in this revision

Viewing changes to src/lib/crypto/krb/checksum_confounder.c

  • Committer: Package Import Robot
  • Author(s): Sam Hartman
  • Date: 2011-12-01 19:34:41 UTC
  • mfrom: (28.1.14 sid)
  • Revision ID: package-import@ubuntu.com-20111201193441-9tipg3aru1jsidyv
Tags: 1.10+dfsg~alpha1-6
* Fix segfault with unknown hostnames in krb5_sname_to_principal,
  Closes: #650671
* Indicate that this library breaks libsmbclient versions that depend on
  krb5_locate_kdc, Closes: #650603, #650611

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 
2
/* lib/crypto/krb/checksum_confounder.c */
 
3
/*
 
4
 * Copyright (C) 2009 by the Massachusetts Institute of Technology.
 
5
 * All rights reserved.
 
6
 *
 
7
 * Export of this software from the United States of America may
 
8
 *   require a specific license from the United States Government.
 
9
 *   It is the responsibility of any person or organization contemplating
 
10
 *   export to obtain such a license before exporting.
 
11
 *
 
12
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
 
13
 * distribute this software and its documentation for any purpose and
 
14
 * without fee is hereby granted, provided that the above copyright
 
15
 * notice appear in all copies and that both that copyright notice and
 
16
 * this permission notice appear in supporting documentation, and that
 
17
 * the name of M.I.T. not be used in advertising or publicity pertaining
 
18
 * to distribution of the software without specific, written prior
 
19
 * permission.  Furthermore if you modify this software you must label
 
20
 * your software as modified software and not distribute it in such a
 
21
 * fashion that it might be confused with the original M.I.T. software.
 
22
 * M.I.T. makes no representations about the suitability of
 
23
 * this software for any purpose.  It is provided "as is" without express
 
24
 * or implied warranty.
 
25
 */
 
26
 
 
27
/*
 
28
 * Confounder checksum implementation, using tokens of the form:
 
29
 *   enc(xorkey, confounder | hash(confounder | data))
 
30
 * where xorkey is the key XOR'd with 0xf0 bytes.
 
31
 */
 
32
 
 
33
#include "crypto_int.h"
 
34
 
 
35
/* Derive a key by XOR with 0xF0 bytes. */
 
36
static krb5_error_code
 
37
mk_xorkey(krb5_key origkey, krb5_key *xorkey)
 
38
{
 
39
    krb5_error_code retval = 0;
 
40
    unsigned char *xorbytes;
 
41
    krb5_keyblock xorkeyblock;
 
42
    size_t i = 0;
 
43
 
 
44
    xorbytes = malloc(origkey->keyblock.length);
 
45
    if (xorbytes == NULL)
 
46
        return ENOMEM;
 
47
    memcpy(xorbytes, origkey->keyblock.contents, origkey->keyblock.length);
 
48
    for (i = 0; i < origkey->keyblock.length; i++)
 
49
        xorbytes[i] ^= 0xf0;
 
50
 
 
51
    /* Do a shallow copy here. */
 
52
    xorkeyblock = origkey->keyblock;
 
53
    xorkeyblock.contents = xorbytes;
 
54
 
 
55
    retval = krb5_k_create_key(0, &xorkeyblock, xorkey);
 
56
    zapfree(xorbytes, sizeof(xorbytes));
 
57
    return retval;
 
58
}
 
59
 
 
60
krb5_error_code
 
61
krb5int_confounder_checksum(const struct krb5_cksumtypes *ctp,
 
62
                            krb5_key key, krb5_keyusage usage,
 
63
                            const krb5_crypto_iov *data, size_t num_data,
 
64
                            krb5_data *output)
 
65
{
 
66
    krb5_error_code ret;
 
67
    krb5_data conf, hashval;
 
68
    krb5_key xorkey = NULL;
 
69
    krb5_crypto_iov *hash_iov, iov;
 
70
    size_t blocksize = ctp->enc->block_size, hashsize = ctp->hash->hashsize;
 
71
 
 
72
    /* Partition the output buffer into confounder and hash. */
 
73
    conf = make_data(output->data, blocksize);
 
74
    hashval = make_data(output->data + blocksize, hashsize);
 
75
 
 
76
    /* Create the confounder. */
 
77
    ret = krb5_c_random_make_octets(NULL, &conf);
 
78
    if (ret != 0)
 
79
        return ret;
 
80
 
 
81
    ret = mk_xorkey(key, &xorkey);
 
82
    if (ret)
 
83
        return ret;
 
84
 
 
85
    /* Hash the confounder, then the input data. */
 
86
    hash_iov = k5alloc((num_data + 1) * sizeof(krb5_crypto_iov), &ret);
 
87
    if (hash_iov == NULL)
 
88
        goto cleanup;
 
89
    hash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
 
90
    hash_iov[0].data = conf;
 
91
    memcpy(hash_iov + 1, data, num_data * sizeof(krb5_crypto_iov));
 
92
    ret = ctp->hash->hash(hash_iov, num_data + 1, &hashval);
 
93
    if (ret != 0)
 
94
        goto cleanup;
 
95
 
 
96
    /* Confounder and hash are in output buffer; encrypt them in place. */
 
97
    iov.flags = KRB5_CRYPTO_TYPE_DATA;
 
98
    iov.data = *output;
 
99
    ret = ctp->enc->encrypt(xorkey, NULL, &iov, 1);
 
100
 
 
101
cleanup:
 
102
    free(hash_iov);
 
103
    krb5_k_free_key(NULL, xorkey);
 
104
    return ret;
 
105
}
 
106
 
 
107
krb5_error_code krb5int_confounder_verify(const struct krb5_cksumtypes *ctp,
 
108
                                          krb5_key key, krb5_keyusage usage,
 
109
                                          const krb5_crypto_iov *data,
 
110
                                          size_t num_data,
 
111
                                          const krb5_data *input,
 
112
                                          krb5_boolean *valid)
 
113
{
 
114
    krb5_error_code ret;
 
115
    unsigned char *plaintext = NULL;
 
116
    krb5_key xorkey = NULL;
 
117
    krb5_data computed = empty_data();
 
118
    krb5_crypto_iov *hash_iov = NULL, iov;
 
119
    size_t blocksize = ctp->enc->block_size, hashsize = ctp->hash->hashsize;
 
120
 
 
121
    plaintext = k5alloc(input->length, &ret);
 
122
    if (plaintext == NULL)
 
123
        return ret;
 
124
 
 
125
    ret = mk_xorkey(key, &xorkey);
 
126
    if (ret != 0)
 
127
        goto cleanup;
 
128
 
 
129
    /* Decrypt the input checksum. */
 
130
    iov.flags = KRB5_CRYPTO_TYPE_DATA;
 
131
    iov.data = make_data(plaintext, input->length);
 
132
    memcpy(plaintext, input->data, input->length);
 
133
    ret = ctp->enc->decrypt(xorkey, NULL, &iov, 1);
 
134
    if (ret != 0)
 
135
        goto cleanup;
 
136
 
 
137
    /* Hash the confounder, then the input data. */
 
138
    hash_iov = k5alloc((num_data + 1) * sizeof(krb5_crypto_iov), &ret);
 
139
    if (hash_iov == NULL)
 
140
        goto cleanup;
 
141
    hash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
 
142
    hash_iov[0].data = make_data(plaintext, blocksize);
 
143
    memcpy(hash_iov + 1, data, num_data * sizeof(krb5_crypto_iov));
 
144
    ret = alloc_data(&computed, hashsize);
 
145
    if (ret != 0)
 
146
        goto cleanup;
 
147
    ret = ctp->hash->hash(hash_iov, num_data + 1, &computed);
 
148
    if (ret != 0)
 
149
        goto cleanup;
 
150
 
 
151
    /* Compare the decrypted hash to the computed one. */
 
152
    *valid = (memcmp(plaintext + blocksize, computed.data, hashsize) == 0);
 
153
 
 
154
cleanup:
 
155
    zapfree(plaintext, input->length);
 
156
    zapfree(computed.data, hashsize);
 
157
    free(hash_iov);
 
158
    krb5_k_free_key(NULL, xorkey);
 
159
    return ret;
 
160
}