]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/CryptoSupport.c
mDNSResponder-544.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / CryptoSupport.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2011 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
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_key_bytes = 4096 / 8; // max DNSSEC supported modulus is 4096 bits
354 static const int max_exp_bytes = 3; // DNSSEC supports 1 or 3 bytes for exponent
355 static const int asn1_cmd_bytes = 3; // since there is an ASN1 SEQ and two INTs
356 //static const int asn1_max_len_bytes = asn1_cmd_bytes * 3; // capped at 3 due to max payload size
357 static const int asn1_max_len_bytes = 3 * 3; // capped at 3 due to max payload size
358 unsigned char asn1[max_key_bytes + 1 + max_exp_bytes + asn1_cmd_bytes + asn1_max_len_bytes]; // +1 is for leading 0 for non negative asn1 number
359 const mDNSu8 *modulus;
360 unsigned int modulus_length;
361 unsigned int exp_length;
362 mDNSu32 index = 0;
363 mDNSu32 asn1_length = 0;
364 unsigned int i;
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 exp_length = data[0];
376
377 // we have to have at least len byte + size of exponent
378 if (len < 1+exp_length)
379 return NULL;
380
381 // -1 is for the exp_length byte
382 modulus_length = len - 1 - exp_length;
383
384 // rfc3110 limits modulus to 4096 bits
385 if (modulus_length > 512)
386 return NULL;
387
388 if (modulus_length < 1)
389 return NULL;
390
391 // add 1 to modulus length for pre-ceding 0 t make ASN1 value non-negative
392 ++modulus_length;
393
394 // 1 is to skip exp_length byte
395 modulus = &data[1+exp_length];
396
397 // 2 bytes for commands since first doesn't count
398 // 2 bytes for min 1 byte length field
399 asn1_length = modulus_length + exp_length + 2 + 2;
400
401 // account for modulus length causing INT length field to grow
402 if (modulus_length > 0xFF)
403 asn1_length += 2;
404 else if (modulus_length >= 128)
405 ++asn1_length;
406
407 // Construct ASN1 formatted public key
408 // Write ASN1 SEQ byte
409 asn1[index++] = 0x30;
410
411 // Write ASN1 length for SEQ
412 if (asn1_length < 128)
413 {
414 asn1[index++] = asn1_length & 0xFF;
415 }
416 else
417 {
418 asn1[index++] = (0x80 | ((asn1_length & 0xFF00) ? 2 : 1));
419 if (asn1_length & 0xFF00)
420 asn1[index++] = (asn1_length & 0xFF00) >> 8;
421 asn1[index++] = asn1_length & 0xFF;
422 }
423
424 // Write ASN1 INT for modulus
425 asn1[index++] = 0x02;
426 // Write ASN1 length for INT
427 if (modulus_length < 128)
428 {
429 asn1[index++] = asn1_length & 0xFF;
430 }
431 else
432 {
433 asn1[index++] = 0x80 | ((modulus_length & 0xFF00) ? 2 : 1);
434 if (modulus_length & 0xFF00)
435 asn1[index++] = (modulus_length & 0xFF00) >> 8;
436 asn1[index++] = modulus_length & 0xFF;
437 }
438
439 // Write preceding 0 so our integer isn't negative
440 asn1[index++] = 0x00;
441 // Write actual modulus (-1 for preceding 0)
442 memcpy(&asn1[index], (void *)modulus, modulus_length-1);
443 index += modulus_length-1;
444
445 // Write ASN1 INT for exponent
446 asn1[index++] = 0x02;
447 // Write ASN1 length for INT
448 asn1[index++] = exp_length & 0xFF;
449 // Write exponent bytes
450 for (i = 1; i <= exp_length; i++)
451 asn1[index++] = data[i];
452
453 #if TARGET_OS_IPHONE
454 // index contains bytes written, use it for length
455 return (SecKeyCreateRSAPublicKey(NULL, asn1, index, kSecKeyEncodingPkcs1));
456 #else
457 return (SecKeyCreateRSAPublicKey_OSX(asn1, index));
458 #endif
459 }
460
461 #if TARGET_OS_IPHONE
462 mDNSlocal mStatus rsa_sha_verify(AlgContext *ctx, mDNSu8 *key, mDNSu32 keylen, mDNSu8 *signature, mDNSu32 siglen)
463 {
464 SecKeyRef keyref;
465 OSStatus result;
466 mDNSu8 digest[CC_SHA512_DIGEST_LENGTH];
467 int digestlen;
468 int cryptoAlg;
469
470 switch (ctx->alg)
471 {
472 case CRYPTO_RSA_NSEC3_SHA1:
473 case CRYPTO_RSA_SHA1:
474 cryptoAlg = kSecPaddingPKCS1SHA1;
475 digestlen = CC_SHA1_DIGEST_LENGTH;
476 CC_SHA1_Final(digest, (CC_SHA1_CTX *)ctx->context);
477 break;
478 case CRYPTO_RSA_SHA256:
479 cryptoAlg = kSecPaddingPKCS1SHA256;
480 digestlen = CC_SHA256_DIGEST_LENGTH;
481 CC_SHA256_Final(digest, (CC_SHA256_CTX *)ctx->context);
482 break;
483 case CRYPTO_RSA_SHA512:
484 cryptoAlg = kSecPaddingPKCS1SHA512;
485 digestlen = CC_SHA512_DIGEST_LENGTH;
486 CC_SHA512_Final(digest, (CC_SHA512_CTX *)ctx->context);
487 break;
488 default:
489 LogMsg("rsa_sha_verify: Unsupported algorithm %d", ctx->alg);
490 return mStatus_BadParamErr;
491 }
492
493 keyref = rfc3110_import(key, keylen);
494 if (!keyref)
495 {
496 LogMsg("rsa_sha_verify: Error decoding rfc3110 key data");
497 return mStatus_NoMemoryErr;
498 }
499 result = SecKeyRawVerify(keyref, cryptoAlg, digest, digestlen, signature, siglen);
500 CFRelease(keyref);
501 if (result != noErr)
502 {
503 LogMsg("rsa_sha_verify: Failed for alg %d", ctx->alg);
504 return mStatus_BadParamErr;
505 }
506 else
507 {
508 LogInfo("rsa_sha_verify: Passed for alg %d", ctx->alg);
509 return mStatus_NoError;
510 }
511 }
512 #else // TARGET_OS_IPHONE
513
514 mDNSlocal SecKeyRef SecKeyCreateRSAPublicKey_OSX(unsigned char *asn1, int length)
515 {
516 SecKeyRef result = NULL;
517
518 SecExternalFormat extFormat = kSecFormatBSAFE;
519 SecExternalItemType itemType = kSecItemTypePublicKey;
520 CFArrayRef outArray = NULL;
521
522 CFDataRef keyData = CFDataCreate(NULL, asn1, length);
523 if (!keyData)
524 return NULL;
525
526 OSStatus err = SecItemImport(keyData, NULL, &extFormat, &itemType, 0, NULL, NULL, &outArray);
527
528 CFRelease(keyData);
529 if (noErr != err || outArray == NULL)
530 {
531 if (outArray)
532 CFRelease(outArray);
533 return NULL;
534 }
535
536 result = (SecKeyRef)CFArrayGetValueAtIndex(outArray, 0);
537 if (result == NULL)
538 {
539 CFRelease(outArray);
540 return NULL;
541 }
542
543 CFRetain(result);
544 CFRelease(outArray);
545 return result;
546 }
547
548 mDNSlocal Boolean VerifyData(SecKeyRef key, CFStringRef digestStr, mDNSu8 *digest, int dlen, int digestlenAttr, mDNSu8 *sig, int siglen, CFStringRef digest_type)
549 {
550 CFErrorRef error;
551 Boolean ret;
552
553 CFDataRef signature = CFDataCreate(NULL, sig, siglen);
554 if (!signature)
555 return false;
556
557 SecTransformRef verifyXForm = SecVerifyTransformCreate(key, signature, &error);
558 CFRelease(signature);
559 if (verifyXForm == NULL)
560 {
561 return false;
562 }
563
564 // tell the transform what type of data it is geting
565 if (!SecTransformSetAttribute(verifyXForm, kSecInputIsAttributeName, digest_type, &error))
566 {
567 LogMsg("VerifyData: SecTransformSetAttribute digest_type");
568 goto err;
569 }
570
571 if (!SecTransformSetAttribute(verifyXForm, kSecDigestTypeAttribute, digestStr, &error))
572 {
573 LogMsg("VerifyData: SecTransformSetAttribute digestStr");
574 goto err;
575 }
576
577 CFNumberRef digestLengthRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &digestlenAttr);
578 if (digestLengthRef == NULL)
579 {
580 LogMsg("VerifyData: CFNumberCreate failed");
581 goto err;
582 }
583
584 ret = SecTransformSetAttribute(verifyXForm, kSecDigestLengthAttribute, digestLengthRef, &error);
585 CFRelease(digestLengthRef);
586 if (!ret)
587 {
588 LogMsg("VerifyData: SecTransformSetAttribute digestLengthRef");
589 goto err;
590 }
591
592 CFDataRef dataToSign = CFDataCreate(NULL, digest, dlen);
593 if (dataToSign == NULL)
594 {
595 LogMsg("VerifyData: CFDataCreate failed");
596 goto err;
597 }
598
599 ret = SecTransformSetAttribute(verifyXForm, kSecTransformInputAttributeName, dataToSign, &error);
600 CFRelease(dataToSign);
601 if (!ret)
602 {
603 LogMsg("VerifyData: SecTransformSetAttribute TransformAttributeName");
604 goto err;
605 }
606
607 CFBooleanRef boolRef = SecTransformExecute(verifyXForm, &error);
608 CFRelease(verifyXForm);
609
610 if (error != NULL)
611 {
612 CFStringRef errStr = CFErrorCopyDescription(error);
613 char errorbuf[128];
614 errorbuf[0] = 0;
615 if (errStr != NULL)
616 {
617 if (!CFStringGetCString(errStr, errorbuf, sizeof(errorbuf), kCFStringEncodingUTF8))
618 {
619 LogMsg("VerifyData: CFStringGetCString failed");
620 }
621 }
622 LogMsg("VerifyData: SecTransformExecute failed with %s", errorbuf);
623 return false;
624 }
625 return CFEqual(boolRef, kCFBooleanTrue);
626 err:
627 CFRelease(verifyXForm);
628 return false;
629 }
630
631 mDNSlocal mStatus rsa_sha_verify(AlgContext *ctx, mDNSu8 *key, mDNSu32 keylen, mDNSu8 *signature, mDNSu32 siglen)
632 {
633 SecKeyRef keyref;
634 mDNSu8 digest[CC_SHA512_DIGEST_LENGTH];
635 int digestlen;
636 int digestlenAttr;
637 CFStringRef digestStr;
638 mDNSBool ret;
639
640 switch (ctx->alg)
641 {
642 case CRYPTO_RSA_NSEC3_SHA1:
643 case CRYPTO_RSA_SHA1:
644 digestStr = kSecDigestSHA1;
645 digestlen = CC_SHA1_DIGEST_LENGTH;
646 digestlenAttr = 0;
647 CC_SHA1_Final(digest, (CC_SHA1_CTX *)ctx->context);
648 break;
649 case CRYPTO_RSA_SHA256:
650 digestStr = kSecDigestSHA2;
651 digestlen = CC_SHA256_DIGEST_LENGTH;
652 digestlenAttr = 256;
653 CC_SHA256_Final(digest, (CC_SHA256_CTX *)ctx->context);
654 break;
655 case CRYPTO_RSA_SHA512:
656 digestStr = kSecDigestSHA2;
657 digestlen = CC_SHA512_DIGEST_LENGTH;
658 digestlenAttr = 512;
659 CC_SHA512_Final(digest, (CC_SHA512_CTX *)ctx->context);
660 break;
661 default:
662 LogMsg("rsa_sha_verify: Unsupported algorithm %d", ctx->alg);
663 return mStatus_BadParamErr;
664 }
665
666 keyref = rfc3110_import(key, keylen);
667 if (!keyref)
668 {
669 LogMsg("rsa_sha_verify: Error decoding rfc3110 key data");
670 return mStatus_NoMemoryErr;
671 }
672 ret = VerifyData(keyref, digestStr, digest, digestlen, digestlenAttr, signature, siglen, kSecInputIsDigest);
673 CFRelease(keyref);
674 if (!ret)
675 {
676 LogMsg("rsa_sha_verify: Failed for alg %d", ctx->alg);
677 return mStatus_BadParamErr;
678 }
679 else
680 {
681 LogInfo("rsa_sha_verify: Passed for alg %d", ctx->alg);
682 return mStatus_NoError;
683 }
684 }
685 #endif // TARGET_OS_IPHONE
686
687 AlgFuncs sha_funcs = {sha_create, sha_destroy, sha_len, sha_add, sha_verify, mDNSNULL, sha_final};
688 AlgFuncs rsa_sha_funcs = {rsa_sha_create, rsa_sha_destroy, rsa_sha_len, rsa_sha_add, rsa_sha_verify, mDNSNULL, mDNSNULL};
689 AlgFuncs enc_funcs = {enc_create, enc_destroy, mDNSNULL, enc_add, mDNSNULL, enc_encode, mDNSNULL};
690
691 #ifndef DNSSEC_DISABLED
692
693 mDNSexport mStatus DNSSECCryptoInit(mDNS *const m)
694 {
695 mStatus result;
696
697 result = DigestAlgInit(SHA1_DIGEST_TYPE, &sha_funcs);
698 if (result != mStatus_NoError)
699 return result;
700 result = DigestAlgInit(SHA256_DIGEST_TYPE, &sha_funcs);
701 if (result != mStatus_NoError)
702 return result;
703 result = CryptoAlgInit(CRYPTO_RSA_SHA1, &rsa_sha_funcs);
704 if (result != mStatus_NoError)
705 return result;
706 result = CryptoAlgInit(CRYPTO_RSA_NSEC3_SHA1, &rsa_sha_funcs);
707 if (result != mStatus_NoError)
708 return result;
709 result = CryptoAlgInit(CRYPTO_RSA_SHA256, &rsa_sha_funcs);
710 if (result != mStatus_NoError)
711 return result;
712 result = CryptoAlgInit(CRYPTO_RSA_SHA512, &rsa_sha_funcs);
713 if (result != mStatus_NoError)
714 return result;
715 result = EncAlgInit(ENC_BASE32, &enc_funcs);
716 if (result != mStatus_NoError)
717 return result;
718 result = EncAlgInit(ENC_BASE64, &enc_funcs);
719 if (result != mStatus_NoError)
720 return result;
721
722 result = DNSSECPlatformInit(m);
723
724 return result;
725 }
726
727 #else // !DNSSEC_DISABLED
728
729 mDNSexport mStatus DNSSECCryptoInit(mDNS *const m)
730 {
731 (void) m;
732
733 return mStatus_NoError;
734 }
735
736 #endif // !DNSSEC_DISABLED
737
738