]> git.saurik.com Git - apple/mdnsresponder.git/blob - ServiceRegistration/hmac-openssl.c
mDNSResponder-1310.40.42.tar.gz
[apple/mdnsresponder.git] / ServiceRegistration / hmac-openssl.c
1 /* hmac-openssl.c
2 *
3 * Copyright (c) 2019 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * Hashed message authentication code functions using OpenSSL.
18 */
19
20 #include <stdio.h>
21 #include <arpa/inet.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <errno.h>
27
28 #include "srp.h"
29 #include "dns-msg.h"
30 #define SRP_CRYPTO_OPENSSL_INTERNAL
31 #include "srp-crypto.h"
32
33 // Function to generate a signature given some data and a private key
34 void
35 srp_hmac_iov(hmac_key_t *key, uint8_t *output, size_t max, struct iovec *iov, int count)
36 {
37 int status;
38 char errbuf[64];
39 uint8_t kipad[SRP_SHA256_BLOCK_SIZE], kopad[SRP_SHA256_BLOCK_SIZE], intermediate[SRP_SHA256_HASH_SIZE];
40 EVP_MD_CTX inner, outer;
41 const EVP_MD md;
42 int i;
43
44 if (key->algorithm != SRP_HMAC_TYPE_SHA256) {
45 ERROR("srp_hmac_iov: unsupported HMAC hash algorithm: %d", key->algorithm);
46 return;
47 }
48 if (max < SRP_SHA256_HASH_SIZE) {
49 ERROR("srp_hmac_iov: not enough space in output buffer (%lu) for hash (%d).",
50 (unsigned long)max, SRP_SHA256_HASH_SIZE);
51 return;
52 }
53
54 md = EVP_sha256();
55 EVP_MD_CTX_INIT(&inner);
56
57 // If the key is longer than the block size, hash it and use the digest as the key.
58 if (key->length > SRP_SHA256_BLOCK_SIZE) {
59 if ((status = EVP_DigestInit(&inner, md)) != 0) {
60 ERROR("srp_hmac_iov failed to initialize key digest");
61 return;
62 }
63 // Compute H(K)
64 if ((status = EVP_DigestUpdate(&inner, key, key->length)) != 0) {
65 ERROR("srp_hmac_iov failed to hash key");
66 return;
67 }
68 if ((status = EVP_DigestFinal(&inner, intermediate, SRP_SHA256_HASH_SIZE)) != 0) {
69 ERROR("srp_hmac_iov failed to digest key");
70 return;
71 }
72 EVP_MD_CTX_INIT(&inner);
73 }
74
75 // Compute key ^ kipad and key ^ kopad
76 for (i = 0; i < SRP_SHA256_BLOCK_SIZE; i++) {
77 uint8_t byte = i >= key->length ? 0 : key->secret[i];
78 kipad[i] = byte ^ 0x36;
79 kopad[i] = byte ^ 0x5c;
80 }
81
82 if ((status = EVP_DigestInit(&inner, md)) != 0) {
83 ERROR("srp_hmac_iov failed to initialize inner digest");
84 return;
85 }
86 // Compute H(K xor ipad, text)
87 if ((status = EVP_DigestUpdate(&inner, kipad, SRP_SHA256_BLOCK_SIZE)) != 0) {
88 ERROR("srp_hmac_iov failed to hash ipad to inner digest");
89 return;
90 }
91 for (i = 0; i < count; i++) {
92 if ((status = EVP_DigestUpdate(&inner, iov[i].iov_base, iov[i].iov_len)) != 0) {
93 ERROR("srp_hmac_iov failed to hash chunk %d to inner digest", i);
94 return;
95 }
96 }
97 if ((status = EVP_DigestFinal(&inner, intermediate, SRP_SHA256_HASH_SIZE)) != 0) {
98 ERROR("srp_hmac_iov failed to hash ipad to inner digest");
99 return;
100 }
101
102 // Compute H(K xor opad, H(K xor ipad, text))
103 EVP_MD_CTX_INIT(&outer);
104 if ((status = EVP_DigestInit(&outer, md)) != 0) {
105 ERROR("srp_hmac_iov failed to initialize outer digest");
106 return;
107 }
108 if ((status = EVP_DigestUpdate(&outer, kopad, SRP_SHA256_BLOCK_SIZE)) != 0) {
109 ERROR("srp_hmac_iov failed to hash outer pad");
110 return;
111 goto kablooie;
112 }
113 if ((status = EVP_DigestUpdate(&outer, intermediate, SRP_SHA256_HASH_SIZE)) != 0) {
114 ERROR("srp_hmac_iov failed to hash outer digest");
115 return;
116 goto kablooie;
117 }
118 if ((status = EVP_DigestFinal(&outer, output, max)) != 0) {
119 ERROR("srp_hmac_iov failed to hash outer outer pad with inner digest");
120 return;
121 }
122 // Bob's your uncle...
123 }
124
125 int
126 srp_base64_parse(char *src, size_t *len_ret, uint8_t *buf, size_t buflen)
127 {
128 size_t slen = strlen(src);
129 int ret = mbedtls_base64_decode(buf, buflen, len_ret, (const unsigned char *)src, slen);
130 if (ret == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
131 return ENOBUFS;
132 } else if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) {
133 return EILSEQ;
134 } else if (ret < 0) {
135 return EINVAL;
136 }
137 return 0;
138 }
139
140 // Local Variables:
141 // mode: C
142 // tab-width: 4
143 // c-file-style: "bsd"
144 // c-basic-offset: 4
145 // fill-column: 108
146 // indent-tabs-mode: nil
147 // End: