Imported Upstream version 1.10.2
[platform/upstream/krb5.git] / src / lib / crypto / openssl / hmac.c
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/crypto/openssl/hmac.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  * Copyright (C) 1998 by the FundsXpress, INC.
29  *
30  * All rights reserved.
31  *
32  * Export of this software from the United States of America may require
33  * a specific license from the United States Government.  It is the
34  * responsibility of any person or organization contemplating export to
35  * obtain such a license before exporting.
36  *
37  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
38  * distribute this software and its documentation for any purpose and
39  * without fee is hereby granted, provided that the above copyright
40  * notice appear in all copies and that both that copyright notice and
41  * this permission notice appear in supporting documentation, and that
42  * the name of FundsXpress. not be used in advertising or publicity pertaining
43  * to distribution of the software without specific, written prior
44  * permission.  FundsXpress makes no representations about the suitability of
45  * this software for any purpose.  It is provided "as is" without express
46  * or implied warranty.
47  *
48  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
49  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
50  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
51  */
52
53
54 #include "crypto_int.h"
55 #include <openssl/hmac.h>
56 #include <openssl/evp.h>
57
58 /*
59  * the HMAC transform looks like:
60  *
61  * H(K XOR opad, H(K XOR ipad, text))
62  *
63  * where H is a cryptographic hash
64  * K is an n byte key
65  * ipad is the byte 0x36 repeated blocksize times
66  * opad is the byte 0x5c repeated blocksize times
67  * and text is the data being protected
68  */
69
70 static const EVP_MD *
71 map_digest(const struct krb5_hash_provider *hash)
72 {
73     if (!strncmp(hash->hash_name, "SHA1",4))
74         return EVP_sha1();
75     else if (!strncmp(hash->hash_name, "MD5", 3))
76         return EVP_md5();
77     else if (!strncmp(hash->hash_name, "MD4", 3))
78         return EVP_md4();
79     else
80         return NULL;
81 }
82
83 krb5_error_code
84 krb5int_hmac_keyblock(const struct krb5_hash_provider *hash,
85                       const krb5_keyblock *keyblock,
86                       const krb5_crypto_iov *data, size_t num_data,
87                       krb5_data *output)
88 {
89     unsigned int i = 0, md_len = 0;
90     unsigned char md[EVP_MAX_MD_SIZE];
91     HMAC_CTX c;
92     size_t hashsize, blocksize;
93
94     hashsize = hash->hashsize;
95     blocksize = hash->blocksize;
96
97     if (keyblock->length > blocksize)
98         return(KRB5_CRYPTO_INTERNAL);
99     if (output->length < hashsize)
100         return(KRB5_BAD_MSIZE);
101
102     if (!map_digest(hash))
103         return(KRB5_CRYPTO_INTERNAL); // unsupported alg
104
105     HMAC_CTX_init(&c);
106     HMAC_Init(&c, keyblock->contents, keyblock->length, map_digest(hash));
107     for (i = 0; i < num_data; i++) {
108         krb5_crypto_iov *iov = &data[i];
109
110         if (SIGN_IOV(iov))
111             HMAC_Update(&c, (unsigned char*) iov->data.data, iov->data.length);
112     }
113     HMAC_Final(&c,(unsigned char *)md, &md_len);
114     if ( md_len <= output->length) {
115         output->length = md_len;
116         memcpy(output->data, md, output->length);
117     }
118     HMAC_CTX_cleanup(&c);
119     return 0;
120
121
122 }
123
124 krb5_error_code
125 krb5int_hmac(const struct krb5_hash_provider *hash, krb5_key key,
126              const krb5_crypto_iov *data, size_t num_data,
127              krb5_data *output)
128 {
129     return krb5int_hmac_keyblock(hash, &key->keyblock, data, num_data, output);
130 }