]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/CryptoSupport.c
mDNSResponder-878.230.2.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / CryptoSupport.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2011-2013 Apple 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
18 // ***************************************************************************
19 // CryptoSupport.c
20 // Supporting routines for DNSSEC crypto
21 // ***************************************************************************
22
23 #include "mDNSEmbeddedAPI.h"
24 #include <CommonCrypto/CommonDigest.h> // For Hash algorithms SHA1 etc.
25 #include <dispatch/dispatch.h> // For Base32/Base64 encoding/decoding
26 #include <dispatch/private.h> // dispatch_data_create_with_transform
27 #include "CryptoAlg.h"
28 #include "CryptoSupport.h"
29 #include "dnssec.h"
30 #include "DNSSECSupport.h"
31
32 #if TARGET_OS_IPHONE
33 #include "SecRSAKey.h" // For RSA_SHA1 etc. verification
34 #else
35 #include <Security/Security.h>
36 #endif
37
38 #if !TARGET_OS_IPHONE
39 mDNSlocal SecKeyRef SecKeyCreateRSAPublicKey_OSX(unsigned char *asn1, int length);
40 #endif
41
42 typedef struct
43 {
44 dispatch_data_t encData;
45 dispatch_data_t encMap;
46 dispatch_data_t encNULL;
47 }encContext;
48
49 mDNSlocal mStatus enc_create(AlgContext *ctx)
50 {
51 encContext *ptr;
52
53 switch (ctx->alg)
54 {
55 case ENC_BASE32:
56 case ENC_BASE64:
57 ptr = (encContext *)mDNSPlatformMemAllocate(sizeof(encContext));
58 if (!ptr) return mStatus_NoMemoryErr;
59 break;
60 default:
61 LogMsg("enc_create: Unsupported algorithm %d", ctx->alg);
62 return mStatus_BadParamErr;
63 }
64 ptr->encData = NULL;
65 ptr->encMap = NULL;
66 // The encoded data is not NULL terminated. So, we concatenate a null byte later when we encode and map
67 // the real data.
68 ptr->encNULL = dispatch_data_create("", 1, dispatch_get_global_queue(0, 0), ^{});
69 if (!ptr->encNULL)
70 {
71 mDNSPlatformMemFree(ptr);
72 return mStatus_NoMemoryErr;
73 }
74 ctx->context = ptr;
75 return mStatus_NoError;
76 }
77
78 mDNSlocal mStatus enc_destroy(AlgContext *ctx)
79 {
80 encContext *ptr = (encContext *)ctx->context;
81 if (ptr->encData) dispatch_release(ptr->encData);
82 if (ptr->encMap) dispatch_release(ptr->encMap);
83 if (ptr->encNULL) dispatch_release(ptr->encNULL);
84 mDNSPlatformMemFree(ptr);
85 return mStatus_NoError;
86 }
87
88 mDNSlocal mStatus enc_add(AlgContext *ctx, const void *data, mDNSu32 len)
89 {
90 switch (ctx->alg)
91 {
92 case ENC_BASE32:
93 case ENC_BASE64:
94 {
95 encContext *ptr = (encContext *)ctx->context;
96 dispatch_data_t src_data = dispatch_data_create(data, len, dispatch_get_global_queue(0, 0), ^{});
97 if (!src_data)
98 {
99 LogMsg("enc_add: dispatch_data_create src failed");
100 return mStatus_BadParamErr;
101 }
102 dispatch_data_t dest_data = dispatch_data_create_with_transform(src_data, DISPATCH_DATA_FORMAT_TYPE_NONE,
103 (ctx->alg == ENC_BASE32 ? DISPATCH_DATA_FORMAT_TYPE_BASE32HEX : DISPATCH_DATA_FORMAT_TYPE_BASE64));
104 dispatch_release(src_data);
105 if (!dest_data)
106 {
107 LogMsg("enc_add: dispatch_data_create dst failed");
108 return mStatus_BadParamErr;
109 }
110 ptr->encData = dest_data;
111
112 return mStatus_NoError;
113 }
114 default:
115 LogMsg("enc_add: Unsupported algorithm %d", ctx->alg);
116 return mStatus_BadParamErr;
117 }
118 }
119
120 mDNSlocal mDNSu8* enc_encode(AlgContext *ctx)
121 {
122 const void *result = NULL;
123
124 switch (ctx->alg)
125 {
126 case ENC_BASE32:
127 case ENC_BASE64:
128 {
129 encContext *ptr = (encContext *)ctx->context;
130 size_t size;
131 dispatch_data_t dest_data = ptr->encData;
132 dispatch_data_t data = dispatch_data_create_concat(dest_data, ptr->encNULL);
133
134 if (!data)
135 {
136 LogMsg("enc_encode: cannot concatenate");
137 return NULL;
138 }
139
140 dispatch_data_t map = dispatch_data_create_map(data, &result, &size);
141 if (!map)
142 {
143 LogMsg("enc_encode: cannot create map %d", ctx->alg);
144 return NULL;
145 }
146 dispatch_release(dest_data);
147 ptr->encData = data;
148 ptr->encMap = map;
149
150 return (mDNSu8 *)result;
151 }
152 default:
153 LogMsg("enc_encode: Unsupported algorithm %d", ctx->alg);
154 return mDNSNULL;
155 }
156 }
157
158 mDNSlocal mStatus sha_create(AlgContext *ctx)
159 {
160 mDNSu8 *ptr;
161 switch (ctx->alg)
162 {
163 case SHA1_DIGEST_TYPE:
164 ptr = mDNSPlatformMemAllocate(sizeof(CC_SHA1_CTX));
165 if (!ptr) return mStatus_NoMemoryErr;
166 CC_SHA1_Init((CC_SHA1_CTX *)ptr);
167 break;
168 case SHA256_DIGEST_TYPE:
169 ptr = mDNSPlatformMemAllocate(sizeof(CC_SHA256_CTX));
170 if (!ptr) return mStatus_NoMemoryErr;
171 CC_SHA256_Init((CC_SHA256_CTX *)ptr);
172 break;
173 default:
174 LogMsg("sha_create: Unsupported algorithm %d", ctx->alg);
175 return mStatus_BadParamErr;
176 }
177 ctx->context = ptr;
178 return mStatus_NoError;
179 }
180
181 mDNSlocal mStatus sha_destroy(AlgContext *ctx)
182 {
183 mDNSPlatformMemFree(ctx->context);
184 return mStatus_NoError;
185 }
186
187 mDNSlocal mDNSu32 sha_len(AlgContext *ctx)
188 {
189 switch (ctx->alg)
190 {
191 case SHA1_DIGEST_TYPE:
192 return CC_SHA1_DIGEST_LENGTH;
193 case SHA256_DIGEST_TYPE:
194 return CC_SHA256_DIGEST_LENGTH;
195 default:
196 LogMsg("sha_len: Unsupported algorithm %d", ctx->alg);
197 return mStatus_BadParamErr;
198 }
199 }
200
201 mDNSlocal mStatus sha_add(AlgContext *ctx, const void *data, mDNSu32 len)
202 {
203 switch (ctx->alg)
204 {
205 case SHA1_DIGEST_TYPE:
206 CC_SHA1_Update((CC_SHA1_CTX *)ctx->context, data, len);
207 break;
208 case SHA256_DIGEST_TYPE:
209 CC_SHA256_Update((CC_SHA256_CTX *)ctx->context, data, len);
210 break;
211 default:
212 LogMsg("sha_add: Unsupported algorithm %d", ctx->alg);
213 return mStatus_BadParamErr;
214 }
215 return mStatus_NoError;
216 }
217
218 mDNSlocal mStatus sha_verify(AlgContext *ctx, mDNSu8 *key, mDNSu32 keylen, mDNSu8 *digestIn, mDNSu32 dlen)
219 {
220 mDNSu8 digest[CC_SHA512_DIGEST_LENGTH];
221 mDNSu32 digestLen;
222
223 (void) key; //unused
224 (void)keylen; //unused
225 switch (ctx->alg)
226 {
227 case SHA1_DIGEST_TYPE:
228 digestLen = CC_SHA1_DIGEST_LENGTH;
229 CC_SHA1_Final(digest, (CC_SHA1_CTX *)ctx->context);
230 break;
231 case SHA256_DIGEST_TYPE:
232 digestLen = CC_SHA256_DIGEST_LENGTH;
233 CC_SHA256_Final(digest, (CC_SHA256_CTX *)ctx->context);
234 break;
235 default:
236 LogMsg("sha_verify: Unsupported algorithm %d", ctx->alg);
237 return mStatus_BadParamErr;
238 }
239 if (dlen != digestLen)
240 {
241 LogMsg("sha_verify(Alg %d): digest len mismatch len %u, expected %u", ctx->alg, (unsigned int)dlen, (unsigned int)digestLen);
242 return mStatus_BadParamErr;
243 }
244 if (!memcmp(digest, digestIn, digestLen))
245 return mStatus_NoError;
246 else
247 return mStatus_NoAuth;
248 }
249
250 mDNSlocal mStatus sha_final(AlgContext *ctx, void *digestOut, mDNSu32 dlen)
251 {
252 mDNSu8 digest[CC_SHA512_DIGEST_LENGTH];
253 mDNSu32 digestLen;
254
255 switch (ctx->alg)
256 {
257 case SHA1_DIGEST_TYPE:
258 digestLen = CC_SHA1_DIGEST_LENGTH;
259 CC_SHA1_Final(digest, (CC_SHA1_CTX *)ctx->context);
260 break;
261 case SHA256_DIGEST_TYPE:
262 digestLen = CC_SHA256_DIGEST_LENGTH;
263 CC_SHA256_Final(digest, (CC_SHA256_CTX *)ctx->context);
264 break;
265 default:
266 LogMsg("sha_final: Unsupported algorithm %d", ctx->alg);
267 return mStatus_BadParamErr;
268 }
269 if (dlen != digestLen)
270 {
271 LogMsg("sha_final(Alg %d): digest len mismatch len %u, expected %u", ctx->alg, (unsigned int)dlen, (unsigned int)digestLen);
272 return mStatus_BadParamErr;
273 }
274 memcpy(digestOut, digest, digestLen);
275 return mStatus_NoError;
276 }
277
278 mDNSlocal mStatus rsa_sha_create(AlgContext *ctx)
279 {
280 mDNSu8 *ptr;
281 switch (ctx->alg)
282 {
283 case CRYPTO_RSA_NSEC3_SHA1:
284 case CRYPTO_RSA_SHA1:
285 ptr = mDNSPlatformMemAllocate(sizeof(CC_SHA1_CTX));
286 if (!ptr) return mStatus_NoMemoryErr;
287 CC_SHA1_Init((CC_SHA1_CTX *)ptr);
288 break;
289 case CRYPTO_RSA_SHA256:
290 ptr = mDNSPlatformMemAllocate(sizeof(CC_SHA256_CTX));
291 if (!ptr) return mStatus_NoMemoryErr;
292 CC_SHA256_Init((CC_SHA256_CTX *)ptr);
293 break;
294 case CRYPTO_RSA_SHA512:
295 ptr = mDNSPlatformMemAllocate(sizeof(CC_SHA512_CTX));
296 if (!ptr) return mStatus_NoMemoryErr;
297 CC_SHA512_Init((CC_SHA512_CTX *)ptr);
298 break;
299 default:
300 LogMsg("rsa_sha_create: Unsupported algorithm %d", ctx->alg);
301 return mStatus_BadParamErr;
302 }
303 ctx->context = ptr;
304 return mStatus_NoError;
305 }
306
307 mDNSlocal mStatus rsa_sha_destroy(AlgContext *ctx)
308 {
309 mDNSPlatformMemFree(ctx->context);
310 return mStatus_NoError;
311 }
312
313 mDNSlocal mDNSu32 rsa_sha_len(AlgContext *ctx)
314 {
315 switch (ctx->alg)
316 {
317 case CRYPTO_RSA_NSEC3_SHA1:
318 case CRYPTO_RSA_SHA1:
319 return CC_SHA1_DIGEST_LENGTH;
320 case CRYPTO_RSA_SHA256:
321 return CC_SHA256_DIGEST_LENGTH;
322 case CRYPTO_RSA_SHA512:
323 return CC_SHA512_DIGEST_LENGTH;
324 default:
325 LogMsg("rsa_sha_len: Unsupported algorithm %d", ctx->alg);
326 return mStatus_BadParamErr;
327 }
328 }
329
330 mDNSlocal mStatus rsa_sha_add(AlgContext *ctx, const void *data, mDNSu32 len)
331 {
332 switch (ctx->alg)
333 {
334 case CRYPTO_RSA_NSEC3_SHA1:
335 case CRYPTO_RSA_SHA1:
336 CC_SHA1_Update((CC_SHA1_CTX *)ctx->context, data, len);
337 break;
338 case CRYPTO_RSA_SHA256:
339 CC_SHA256_Update((CC_SHA256_CTX *)ctx->context, data, len);
340 break;
341 case CRYPTO_RSA_SHA512:
342 CC_SHA512_Update((CC_SHA512_CTX *)ctx->context, data, len);
343 break;
344 default:
345 LogMsg("rsa_sha_add: Unsupported algorithm %d", ctx->alg);
346 return mStatus_BadParamErr;
347 }
348 return mStatus_NoError;
349 }
350
351 mDNSlocal SecKeyRef rfc3110_import(const mDNSu8 *data, const mDNSu32 len)
352 {
353 static const int max_modulus_bytes = 512; // Modulus is limited to 4096 bits (512 octets) in length.
354 static const int max_exp_bytes = 512; // Exponent is limited to 4096 bits (512 octets) in length.
355 static const int asn1_type_bytes = 3; // Since there is an ASN1 SEQ and two INTs.
356 static const int asn1_max_len_bytes = 3 * 3; // Capped at 3 due to max payload size.
357 unsigned char asn1[max_modulus_bytes + 1 + max_exp_bytes + asn1_type_bytes + asn1_max_len_bytes]; // +1 is for leading 0 for non negative asn1 number
358 const mDNSu8 *modulus;
359 unsigned int modulus_length;
360 const mDNSu8 *exponent;
361 unsigned int exp_length;
362 unsigned int num_length_bytes;
363 mDNSu32 index = 0;
364 mDNSu32 asn1_length = 0;
365
366 // Validate Input
367 if (!data)
368 return NULL;
369
370 // we have to have at least 1 byte for the length
371 if (len < 1)
372 return NULL;
373
374 // Parse Modulus and Exponent
375
376 // If the first byte is zero, then the exponent length is in the three-byte format, otherwise the length is in the first byte.
377 if (data[0] == 0)
378 {
379 if (len < 3)
380 return NULL;
381 exp_length = (data[1] << 8) | data[2];
382 num_length_bytes = 3;
383 }
384 else
385 {
386 exp_length = data[0];
387 num_length_bytes = 1;
388 }
389
390 // RFC3110 limits the exponent length to 4096 bits (512 octets).
391 if (exp_length > 512)
392 return NULL;
393
394 // We have to have at least len bytes + size of exponent.
395 if (len < (num_length_bytes + exp_length))
396 return NULL;
397
398 // The modulus is the remaining space.
399 modulus_length = len - (num_length_bytes + exp_length);
400
401 // RFC3110 limits the modulus length to 4096 bits (512 octets).
402 if (modulus_length > 512)
403 return NULL;
404
405 if (modulus_length < 1)
406 return NULL;
407
408 // add 1 to modulus length for pre-ceding 0 t make ASN1 value non-negative
409 ++modulus_length;
410
411 exponent = &data[num_length_bytes];
412 modulus = &data[num_length_bytes + exp_length];
413
414 // 2 bytes for commands since first doesn't count
415 // 2 bytes for min 1 byte length field
416 asn1_length = modulus_length + exp_length + 2 + 2;
417
418 // Account for modulus length causing INT length field to grow.
419 if (modulus_length >= 128)
420 {
421 if (modulus_length > 255)
422 asn1_length += 2;
423 else
424 asn1_length += 1;
425 }
426
427 // Account for exponent length causing INT length field to grow.
428 if (exp_length >= 128)
429 {
430 if (exp_length > 255)
431 asn1_length += 2;
432 else
433 asn1_length += 1;
434 }
435
436 // Construct ASN1 formatted public key
437 // Write ASN1 SEQ byte
438 asn1[index++] = 0x30;
439
440 // Write ASN1 length for SEQ
441 if (asn1_length < 128)
442 {
443 asn1[index++] = asn1_length & 0xFF;
444 }
445 else
446 {
447 asn1[index++] = (0x80 | ((asn1_length > 255) ? 2 : 1));
448 if (asn1_length > 255)
449 asn1[index++] = (asn1_length & 0xFF00) >> 8;
450 asn1[index++] = asn1_length & 0xFF;
451 }
452
453 // Write ASN1 INT for modulus
454 asn1[index++] = 0x02;
455 // Write ASN1 length for INT
456 if (modulus_length < 128)
457 {
458 asn1[index++] = modulus_length & 0xFF;
459 }
460 else
461 {
462 asn1[index++] = 0x80 | ((modulus_length > 255) ? 2 : 1);
463 if (modulus_length > 255)
464 asn1[index++] = (modulus_length & 0xFF00) >> 8;
465 asn1[index++] = modulus_length & 0xFF;
466 }
467
468 // Write preceding 0 so our integer isn't negative
469 asn1[index++] = 0x00;
470 // Write actual modulus (-1 for preceding 0)
471 memcpy(&asn1[index], modulus, modulus_length - 1);
472 index += (modulus_length - 1);
473
474 // Write ASN1 INT for exponent
475 asn1[index++] = 0x02;
476 // Write ASN1 length for INT
477 if (exp_length < 128)
478 {
479 asn1[index++] = exp_length & 0xFF;
480 }
481 else
482 {
483 asn1[index++] = 0x80 | ((exp_length > 255) ? 2 : 1);
484 if (exp_length > 255)
485 asn1[index++] = (exp_length & 0xFF00) >> 8;
486 asn1[index++] = exp_length & 0xFF;
487 }
488 // Write exponent bytes
489 memcpy(&asn1[index], exponent, exp_length);
490 index += exp_length;
491
492 #if TARGET_OS_IPHONE
493 // index contains bytes written, use it for length
494 return (SecKeyCreateRSAPublicKey(NULL, asn1, index, kSecKeyEncodingPkcs1));
495 #else
496 return (SecKeyCreateRSAPublicKey_OSX(asn1, index));
497 #endif
498 }
499
500 #if TARGET_OS_IPHONE
501 mDNSlocal mStatus rsa_sha_verify(AlgContext *ctx, mDNSu8 *key, mDNSu32 keylen, mDNSu8 *signature, mDNSu32 siglen)
502 {
503 SecKeyRef keyref;
504 OSStatus result;
505 mDNSu8 digest[CC_SHA512_DIGEST_LENGTH];
506 int digestlen;
507 int cryptoAlg;
508
509 switch (ctx->alg)
510 {
511 case CRYPTO_RSA_NSEC3_SHA1:
512 case CRYPTO_RSA_SHA1:
513 cryptoAlg = kSecPaddingPKCS1SHA1;
514 digestlen = CC_SHA1_DIGEST_LENGTH;
515 CC_SHA1_Final(digest, (CC_SHA1_CTX *)ctx->context);
516 break;
517 case CRYPTO_RSA_SHA256:
518 cryptoAlg = kSecPaddingPKCS1SHA256;
519 digestlen = CC_SHA256_DIGEST_LENGTH;
520 CC_SHA256_Final(digest, (CC_SHA256_CTX *)ctx->context);
521 break;
522 case CRYPTO_RSA_SHA512:
523 cryptoAlg = kSecPaddingPKCS1SHA512;
524 digestlen = CC_SHA512_DIGEST_LENGTH;
525 CC_SHA512_Final(digest, (CC_SHA512_CTX *)ctx->context);
526 break;
527 default:
528 LogMsg("rsa_sha_verify: Unsupported algorithm %d", ctx->alg);
529 return mStatus_BadParamErr;
530 }
531
532 keyref = rfc3110_import(key, keylen);
533 if (!keyref)
534 {
535 LogMsg("rsa_sha_verify: Error decoding rfc3110 key data");
536 return mStatus_NoMemoryErr;
537 }
538 result = SecKeyRawVerify(keyref, cryptoAlg, digest, digestlen, signature, siglen);
539 CFRelease(keyref);
540 if (result != noErr)
541 {
542 LogMsg("rsa_sha_verify: Failed for alg %d", ctx->alg);
543 return mStatus_BadParamErr;
544 }
545 else
546 {
547 LogInfo("rsa_sha_verify: Passed for alg %d", ctx->alg);
548 return mStatus_NoError;
549 }
550 }
551 #else // TARGET_OS_IPHONE
552
553 mDNSlocal SecKeyRef SecKeyCreateRSAPublicKey_OSX(unsigned char *asn1, int length)
554 {
555 SecKeyRef result = NULL;
556
557 SecExternalFormat extFormat = kSecFormatBSAFE;
558 SecExternalItemType itemType = kSecItemTypePublicKey;
559 CFArrayRef outArray = NULL;
560
561 CFDataRef keyData = CFDataCreate(NULL, asn1, length);
562 if (!keyData)
563 return NULL;
564
565 OSStatus err = SecItemImport(keyData, NULL, &extFormat, &itemType, 0, NULL, NULL, &outArray);
566
567 CFRelease(keyData);
568 if (noErr != err || outArray == NULL)
569 {
570 if (outArray)
571 CFRelease(outArray);
572 return NULL;
573 }
574
575 result = (SecKeyRef)CFArrayGetValueAtIndex(outArray, 0);
576 if (result == NULL)
577 {
578 CFRelease(outArray);
579 return NULL;
580 }
581
582 CFRetain(result);
583 CFRelease(outArray);
584 return result;
585 }
586
587 mDNSlocal Boolean VerifyData(SecKeyRef key, CFStringRef digestStr, mDNSu8 *digest, int dlen, int digestlenAttr, mDNSu8 *sig, int siglen, CFStringRef digest_type)
588 {
589 CFErrorRef error;
590 Boolean ret;
591
592 CFDataRef signature = CFDataCreate(NULL, sig, siglen);
593 if (!signature)
594 return false;
595
596 SecTransformRef verifyXForm = SecVerifyTransformCreate(key, signature, &error);
597 CFRelease(signature);
598 if (verifyXForm == NULL)
599 {
600 return false;
601 }
602
603 // tell the transform what type of data it is geting
604 if (!SecTransformSetAttribute(verifyXForm, kSecInputIsAttributeName, digest_type, &error))
605 {
606 LogMsg("VerifyData: SecTransformSetAttribute digest_type");
607 goto err;
608 }
609
610 if (!SecTransformSetAttribute(verifyXForm, kSecDigestTypeAttribute, digestStr, &error))
611 {
612 LogMsg("VerifyData: SecTransformSetAttribute digestStr");
613 goto err;
614 }
615
616 CFNumberRef digestLengthRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &digestlenAttr);
617 if (digestLengthRef == NULL)
618 {
619 LogMsg("VerifyData: CFNumberCreate failed");
620 goto err;
621 }
622
623 ret = SecTransformSetAttribute(verifyXForm, kSecDigestLengthAttribute, digestLengthRef, &error);
624 CFRelease(digestLengthRef);
625 if (!ret)
626 {
627 LogMsg("VerifyData: SecTransformSetAttribute digestLengthRef");
628 goto err;
629 }
630
631 CFDataRef dataToSign = CFDataCreate(NULL, digest, dlen);
632 if (dataToSign == NULL)
633 {
634 LogMsg("VerifyData: CFDataCreate failed");
635 goto err;
636 }
637
638 ret = SecTransformSetAttribute(verifyXForm, kSecTransformInputAttributeName, dataToSign, &error);
639 CFRelease(dataToSign);
640 if (!ret)
641 {
642 LogMsg("VerifyData: SecTransformSetAttribute TransformAttributeName");
643 goto err;
644 }
645
646 CFBooleanRef boolRef = SecTransformExecute(verifyXForm, &error);
647 ret = boolRef ? CFBooleanGetValue(boolRef) : false;
648 if (boolRef) CFRelease(boolRef);
649 CFRelease(verifyXForm);
650
651 if (error != NULL)
652 {
653 CFStringRef errStr = CFErrorCopyDescription(error);
654 char errorbuf[128];
655 errorbuf[0] = 0;
656 if (errStr != NULL)
657 {
658 if (!CFStringGetCString(errStr, errorbuf, sizeof(errorbuf), kCFStringEncodingUTF8))
659 {
660 LogMsg("VerifyData: CFStringGetCString failed");
661 }
662 CFRelease(errStr);
663 }
664 LogMsg("VerifyData: SecTransformExecute failed with %s", errorbuf);
665 return false;
666 }
667 return ret;
668 err:
669 CFRelease(verifyXForm);
670 return false;
671 }
672
673 mDNSlocal mStatus rsa_sha_verify(AlgContext *ctx, mDNSu8 *key, mDNSu32 keylen, mDNSu8 *signature, mDNSu32 siglen)
674 {
675 SecKeyRef keyref;
676 mDNSu8 digest[CC_SHA512_DIGEST_LENGTH];
677 int digestlen;
678 int digestlenAttr;
679 CFStringRef digestStr;
680 mDNSBool ret;
681
682 switch (ctx->alg)
683 {
684 case CRYPTO_RSA_NSEC3_SHA1:
685 case CRYPTO_RSA_SHA1:
686 digestStr = kSecDigestSHA1;
687 digestlen = CC_SHA1_DIGEST_LENGTH;
688 digestlenAttr = 0;
689 CC_SHA1_Final(digest, (CC_SHA1_CTX *)ctx->context);
690 break;
691 case CRYPTO_RSA_SHA256:
692 digestStr = kSecDigestSHA2;
693 digestlen = CC_SHA256_DIGEST_LENGTH;
694 digestlenAttr = 256;
695 CC_SHA256_Final(digest, (CC_SHA256_CTX *)ctx->context);
696 break;
697 case CRYPTO_RSA_SHA512:
698 digestStr = kSecDigestSHA2;
699 digestlen = CC_SHA512_DIGEST_LENGTH;
700 digestlenAttr = 512;
701 CC_SHA512_Final(digest, (CC_SHA512_CTX *)ctx->context);
702 break;
703 default:
704 LogMsg("rsa_sha_verify: Unsupported algorithm %d", ctx->alg);
705 return mStatus_BadParamErr;
706 }
707
708 keyref = rfc3110_import(key, keylen);
709 if (!keyref)
710 {
711 LogMsg("rsa_sha_verify: Error decoding rfc3110 key data");
712 return mStatus_NoMemoryErr;
713 }
714 ret = VerifyData(keyref, digestStr, digest, digestlen, digestlenAttr, signature, siglen, kSecInputIsDigest);
715 CFRelease(keyref);
716 if (!ret)
717 {
718 LogMsg("rsa_sha_verify: Failed for alg %d", ctx->alg);
719 return mStatus_BadParamErr;
720 }
721 else
722 {
723 LogInfo("rsa_sha_verify: Passed for alg %d", ctx->alg);
724 return mStatus_NoError;
725 }
726 }
727 #endif // TARGET_OS_IPHONE
728
729 AlgFuncs sha_funcs = {sha_create, sha_destroy, sha_len, sha_add, sha_verify, mDNSNULL, sha_final};
730 AlgFuncs rsa_sha_funcs = {rsa_sha_create, rsa_sha_destroy, rsa_sha_len, rsa_sha_add, rsa_sha_verify, mDNSNULL, mDNSNULL};
731 AlgFuncs enc_funcs = {enc_create, enc_destroy, mDNSNULL, enc_add, mDNSNULL, enc_encode, mDNSNULL};
732
733 #ifndef DNSSEC_DISABLED
734
735 mDNSexport mStatus DNSSECCryptoInit(mDNS *const m)
736 {
737 mStatus result;
738
739 result = DigestAlgInit(SHA1_DIGEST_TYPE, &sha_funcs);
740 if (result != mStatus_NoError)
741 return result;
742 result = DigestAlgInit(SHA256_DIGEST_TYPE, &sha_funcs);
743 if (result != mStatus_NoError)
744 return result;
745 result = CryptoAlgInit(CRYPTO_RSA_SHA1, &rsa_sha_funcs);
746 if (result != mStatus_NoError)
747 return result;
748 result = CryptoAlgInit(CRYPTO_RSA_NSEC3_SHA1, &rsa_sha_funcs);
749 if (result != mStatus_NoError)
750 return result;
751 result = CryptoAlgInit(CRYPTO_RSA_SHA256, &rsa_sha_funcs);
752 if (result != mStatus_NoError)
753 return result;
754 result = CryptoAlgInit(CRYPTO_RSA_SHA512, &rsa_sha_funcs);
755 if (result != mStatus_NoError)
756 return result;
757 result = EncAlgInit(ENC_BASE32, &enc_funcs);
758 if (result != mStatus_NoError)
759 return result;
760 result = EncAlgInit(ENC_BASE64, &enc_funcs);
761 if (result != mStatus_NoError)
762 return result;
763
764 result = DNSSECPlatformInit(m);
765
766 return result;
767 }
768
769 #else // !DNSSEC_DISABLED
770
771 mDNSexport mStatus DNSSECCryptoInit(mDNS *const m)
772 {
773 (void) m;
774
775 return mStatus_NoError;
776 }
777
778 #endif // !DNSSEC_DISABLED
779
780