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