1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 // ***************************************************************************
20 // Supporting routines for DNSSEC crypto
21 // ***************************************************************************
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"
30 #include "DNSSECSupport.h"
33 #include "SecRSAKey.h" // For RSA_SHA1 etc. verification
35 #include <Security/Security.h>
39 mDNSlocal SecKeyRef
SecKeyCreateRSAPublicKey_OSX(unsigned char *asn1
, int length
);
44 dispatch_data_t encData
;
45 dispatch_data_t encMap
;
46 dispatch_data_t encNULL
;
49 mDNSlocal mStatus
enc_create(AlgContext
*ctx
)
57 ptr
= (encContext
*)mDNSPlatformMemAllocate(sizeof(encContext
));
58 if (!ptr
) return mStatus_NoMemoryErr
;
61 LogMsg("enc_create: Unsupported algorithm %d", ctx
->alg
);
62 return mStatus_BadParamErr
;
66 // The encoded data is not NULL terminated. So, we concatenate a null byte later when we encode and map
68 ptr
->encNULL
= dispatch_data_create("", 1, dispatch_get_global_queue(0, 0), ^{});
71 mDNSPlatformMemFree(ptr
);
72 return mStatus_NoMemoryErr
;
75 return mStatus_NoError
;
78 mDNSlocal mStatus
enc_destroy(AlgContext
*ctx
)
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
;
88 mDNSlocal mStatus
enc_add(AlgContext
*ctx
, const void *data
, mDNSu32 len
)
95 encContext
*ptr
= (encContext
*)ctx
->context
;
96 dispatch_data_t src_data
= dispatch_data_create(data
, len
, dispatch_get_global_queue(0, 0), ^{});
99 LogMsg("enc_add: dispatch_data_create src failed");
100 return mStatus_BadParamErr
;
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
);
107 LogMsg("enc_add: dispatch_data_create dst failed");
108 return mStatus_BadParamErr
;
110 ptr
->encData
= dest_data
;
112 return mStatus_NoError
;
115 LogMsg("enc_add: Unsupported algorithm %d", ctx
->alg
);
116 return mStatus_BadParamErr
;
120 mDNSlocal mDNSu8
* enc_encode(AlgContext
*ctx
)
122 const void *result
= NULL
;
129 encContext
*ptr
= (encContext
*)ctx
->context
;
131 dispatch_data_t dest_data
= ptr
->encData
;
132 dispatch_data_t data
= dispatch_data_create_concat(dest_data
, ptr
->encNULL
);
136 LogMsg("enc_encode: cannot concatenate");
140 dispatch_data_t map
= dispatch_data_create_map(data
, &result
, &size
);
143 LogMsg("enc_encode: cannot create map %d", ctx
->alg
);
146 dispatch_release(dest_data
);
150 return (mDNSu8
*)result
;
153 LogMsg("enc_encode: Unsupported algorithm %d", ctx
->alg
);
158 mDNSlocal mStatus
sha_create(AlgContext
*ctx
)
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
);
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
);
174 LogMsg("sha_create: Unsupported algorithm %d", ctx
->alg
);
175 return mStatus_BadParamErr
;
178 return mStatus_NoError
;
181 mDNSlocal mStatus
sha_destroy(AlgContext
*ctx
)
183 mDNSPlatformMemFree(ctx
->context
);
184 return mStatus_NoError
;
187 mDNSlocal mDNSu32
sha_len(AlgContext
*ctx
)
191 case SHA1_DIGEST_TYPE
:
192 return CC_SHA1_DIGEST_LENGTH
;
193 case SHA256_DIGEST_TYPE
:
194 return CC_SHA256_DIGEST_LENGTH
;
196 LogMsg("sha_len: Unsupported algorithm %d", ctx
->alg
);
197 return mStatus_BadParamErr
;
201 mDNSlocal mStatus
sha_add(AlgContext
*ctx
, const void *data
, mDNSu32 len
)
205 case SHA1_DIGEST_TYPE
:
206 CC_SHA1_Update((CC_SHA1_CTX
*)ctx
->context
, data
, len
);
208 case SHA256_DIGEST_TYPE
:
209 CC_SHA256_Update((CC_SHA256_CTX
*)ctx
->context
, data
, len
);
212 LogMsg("sha_add: Unsupported algorithm %d", ctx
->alg
);
213 return mStatus_BadParamErr
;
215 return mStatus_NoError
;
218 mDNSlocal mStatus
sha_verify(AlgContext
*ctx
, mDNSu8
*key
, mDNSu32 keylen
, mDNSu8
*digestIn
, mDNSu32 dlen
)
220 mDNSu8 digest
[CC_SHA512_DIGEST_LENGTH
];
224 (void)keylen
; //unused
227 case SHA1_DIGEST_TYPE
:
228 digestLen
= CC_SHA1_DIGEST_LENGTH
;
229 CC_SHA1_Final(digest
, (CC_SHA1_CTX
*)ctx
->context
);
231 case SHA256_DIGEST_TYPE
:
232 digestLen
= CC_SHA256_DIGEST_LENGTH
;
233 CC_SHA256_Final(digest
, (CC_SHA256_CTX
*)ctx
->context
);
236 LogMsg("sha_verify: Unsupported algorithm %d", ctx
->alg
);
237 return mStatus_BadParamErr
;
239 if (dlen
!= digestLen
)
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
;
244 if (!memcmp(digest
, digestIn
, digestLen
))
245 return mStatus_NoError
;
247 return mStatus_NoAuth
;
250 mDNSlocal mStatus
sha_final(AlgContext
*ctx
, void *digestOut
, mDNSu32 dlen
)
252 mDNSu8 digest
[CC_SHA512_DIGEST_LENGTH
];
257 case SHA1_DIGEST_TYPE
:
258 digestLen
= CC_SHA1_DIGEST_LENGTH
;
259 CC_SHA1_Final(digest
, (CC_SHA1_CTX
*)ctx
->context
);
261 case SHA256_DIGEST_TYPE
:
262 digestLen
= CC_SHA256_DIGEST_LENGTH
;
263 CC_SHA256_Final(digest
, (CC_SHA256_CTX
*)ctx
->context
);
266 LogMsg("sha_final: Unsupported algorithm %d", ctx
->alg
);
267 return mStatus_BadParamErr
;
269 if (dlen
!= digestLen
)
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
;
274 memcpy(digestOut
, digest
, digestLen
);
275 return mStatus_NoError
;
278 mDNSlocal mStatus
rsa_sha_create(AlgContext
*ctx
)
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
);
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
);
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
);
300 LogMsg("rsa_sha_create: Unsupported algorithm %d", ctx
->alg
);
301 return mStatus_BadParamErr
;
304 return mStatus_NoError
;
307 mDNSlocal mStatus
rsa_sha_destroy(AlgContext
*ctx
)
309 mDNSPlatformMemFree(ctx
->context
);
310 return mStatus_NoError
;
313 mDNSlocal mDNSu32
rsa_sha_len(AlgContext
*ctx
)
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
;
325 LogMsg("rsa_sha_len: Unsupported algorithm %d", ctx
->alg
);
326 return mStatus_BadParamErr
;
330 mDNSlocal mStatus
rsa_sha_add(AlgContext
*ctx
, const void *data
, mDNSu32 len
)
334 case CRYPTO_RSA_NSEC3_SHA1
:
335 case CRYPTO_RSA_SHA1
:
336 CC_SHA1_Update((CC_SHA1_CTX
*)ctx
->context
, data
, len
);
338 case CRYPTO_RSA_SHA256
:
339 CC_SHA256_Update((CC_SHA256_CTX
*)ctx
->context
, data
, len
);
341 case CRYPTO_RSA_SHA512
:
342 CC_SHA512_Update((CC_SHA512_CTX
*)ctx
->context
, data
, len
);
345 LogMsg("rsa_sha_add: Unsupported algorithm %d", ctx
->alg
);
346 return mStatus_BadParamErr
;
348 return mStatus_NoError
;
351 mDNSlocal SecKeyRef
rfc3110_import(const mDNSu8
*data
, const mDNSu32 len
)
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
;
363 mDNSu32 asn1_length
= 0;
370 // we have to have at least 1 byte for the length
374 // Parse Modulus and Exponent
375 exp_length
= data
[0];
377 // we have to have at least len byte + size of exponent
378 if (len
< 1+exp_length
)
381 // -1 is for the exp_length byte
382 modulus_length
= len
- 1 - exp_length
;
384 // rfc3110 limits modulus to 4096 bits
385 if (modulus_length
> 512)
388 if (modulus_length
< 1)
391 // add 1 to modulus length for pre-ceding 0 t make ASN1 value non-negative
394 // 1 is to skip exp_length byte
395 modulus
= &data
[1+exp_length
];
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;
401 // account for modulus length causing INT length field to grow
402 if (modulus_length
> 0xFF)
404 else if (modulus_length
>= 128)
407 // Construct ASN1 formatted public key
408 // Write ASN1 SEQ byte
409 asn1
[index
++] = 0x30;
411 // Write ASN1 length for SEQ
412 if (asn1_length
< 128)
414 asn1
[index
++] = asn1_length
& 0xFF;
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;
424 // Write ASN1 INT for modulus
425 asn1
[index
++] = 0x02;
426 // Write ASN1 length for INT
427 if (modulus_length
< 128)
429 asn1
[index
++] = asn1_length
& 0xFF;
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;
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;
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
];
454 // index contains bytes written, use it for length
455 return (SecKeyCreateRSAPublicKey(NULL
, asn1
, index
, kSecKeyEncodingPkcs1
));
457 return (SecKeyCreateRSAPublicKey_OSX(asn1
, index
));
462 mDNSlocal mStatus
rsa_sha_verify(AlgContext
*ctx
, mDNSu8
*key
, mDNSu32 keylen
, mDNSu8
*signature
, mDNSu32 siglen
)
466 mDNSu8 digest
[CC_SHA512_DIGEST_LENGTH
];
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
);
478 case CRYPTO_RSA_SHA256
:
479 cryptoAlg
= kSecPaddingPKCS1SHA256
;
480 digestlen
= CC_SHA256_DIGEST_LENGTH
;
481 CC_SHA256_Final(digest
, (CC_SHA256_CTX
*)ctx
->context
);
483 case CRYPTO_RSA_SHA512
:
484 cryptoAlg
= kSecPaddingPKCS1SHA512
;
485 digestlen
= CC_SHA512_DIGEST_LENGTH
;
486 CC_SHA512_Final(digest
, (CC_SHA512_CTX
*)ctx
->context
);
489 LogMsg("rsa_sha_verify: Unsupported algorithm %d", ctx
->alg
);
490 return mStatus_BadParamErr
;
493 keyref
= rfc3110_import(key
, keylen
);
496 LogMsg("rsa_sha_verify: Error decoding rfc3110 key data");
497 return mStatus_NoMemoryErr
;
499 result
= SecKeyRawVerify(keyref
, cryptoAlg
, digest
, digestlen
, signature
, siglen
);
503 LogMsg("rsa_sha_verify: Failed for alg %d", ctx
->alg
);
504 return mStatus_BadParamErr
;
508 LogInfo("rsa_sha_verify: Passed for alg %d", ctx
->alg
);
509 return mStatus_NoError
;
512 #else // TARGET_OS_IPHONE
514 mDNSlocal SecKeyRef
SecKeyCreateRSAPublicKey_OSX(unsigned char *asn1
, int length
)
516 SecKeyRef result
= NULL
;
518 SecExternalFormat extFormat
= kSecFormatBSAFE
;
519 SecExternalItemType itemType
= kSecItemTypePublicKey
;
520 CFArrayRef outArray
= NULL
;
522 CFDataRef keyData
= CFDataCreate(NULL
, asn1
, length
);
526 OSStatus err
= SecItemImport(keyData
, NULL
, &extFormat
, &itemType
, 0, NULL
, NULL
, &outArray
);
529 if (noErr
!= err
|| outArray
== NULL
)
536 result
= (SecKeyRef
)CFArrayGetValueAtIndex(outArray
, 0);
548 mDNSlocal Boolean
VerifyData(SecKeyRef key
, CFStringRef digestStr
, mDNSu8
*digest
, int dlen
, int digestlenAttr
, mDNSu8
*sig
, int siglen
, CFStringRef digest_type
)
553 CFDataRef signature
= CFDataCreate(NULL
, sig
, siglen
);
557 SecTransformRef verifyXForm
= SecVerifyTransformCreate(key
, signature
, &error
);
558 CFRelease(signature
);
559 if (verifyXForm
== NULL
)
564 // tell the transform what type of data it is geting
565 if (!SecTransformSetAttribute(verifyXForm
, kSecInputIsAttributeName
, digest_type
, &error
))
567 LogMsg("VerifyData: SecTransformSetAttribute digest_type");
571 if (!SecTransformSetAttribute(verifyXForm
, kSecDigestTypeAttribute
, digestStr
, &error
))
573 LogMsg("VerifyData: SecTransformSetAttribute digestStr");
577 CFNumberRef digestLengthRef
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberCFIndexType
, &digestlenAttr
);
578 if (digestLengthRef
== NULL
)
580 LogMsg("VerifyData: CFNumberCreate failed");
584 ret
= SecTransformSetAttribute(verifyXForm
, kSecDigestLengthAttribute
, digestLengthRef
, &error
);
585 CFRelease(digestLengthRef
);
588 LogMsg("VerifyData: SecTransformSetAttribute digestLengthRef");
592 CFDataRef dataToSign
= CFDataCreate(NULL
, digest
, dlen
);
593 if (dataToSign
== NULL
)
595 LogMsg("VerifyData: CFDataCreate failed");
599 ret
= SecTransformSetAttribute(verifyXForm
, kSecTransformInputAttributeName
, dataToSign
, &error
);
600 CFRelease(dataToSign
);
603 LogMsg("VerifyData: SecTransformSetAttribute TransformAttributeName");
607 CFBooleanRef boolRef
= SecTransformExecute(verifyXForm
, &error
);
608 CFRelease(verifyXForm
);
612 CFStringRef errStr
= CFErrorCopyDescription(error
);
617 if (!CFStringGetCString(errStr
, errorbuf
, sizeof(errorbuf
), kCFStringEncodingUTF8
))
619 LogMsg("VerifyData: CFStringGetCString failed");
622 LogMsg("VerifyData: SecTransformExecute failed with %s", errorbuf
);
625 return CFEqual(boolRef
, kCFBooleanTrue
);
627 CFRelease(verifyXForm
);
631 mDNSlocal mStatus
rsa_sha_verify(AlgContext
*ctx
, mDNSu8
*key
, mDNSu32 keylen
, mDNSu8
*signature
, mDNSu32 siglen
)
634 mDNSu8 digest
[CC_SHA512_DIGEST_LENGTH
];
637 CFStringRef digestStr
;
642 case CRYPTO_RSA_NSEC3_SHA1
:
643 case CRYPTO_RSA_SHA1
:
644 digestStr
= kSecDigestSHA1
;
645 digestlen
= CC_SHA1_DIGEST_LENGTH
;
647 CC_SHA1_Final(digest
, (CC_SHA1_CTX
*)ctx
->context
);
649 case CRYPTO_RSA_SHA256
:
650 digestStr
= kSecDigestSHA2
;
651 digestlen
= CC_SHA256_DIGEST_LENGTH
;
653 CC_SHA256_Final(digest
, (CC_SHA256_CTX
*)ctx
->context
);
655 case CRYPTO_RSA_SHA512
:
656 digestStr
= kSecDigestSHA2
;
657 digestlen
= CC_SHA512_DIGEST_LENGTH
;
659 CC_SHA512_Final(digest
, (CC_SHA512_CTX
*)ctx
->context
);
662 LogMsg("rsa_sha_verify: Unsupported algorithm %d", ctx
->alg
);
663 return mStatus_BadParamErr
;
666 keyref
= rfc3110_import(key
, keylen
);
669 LogMsg("rsa_sha_verify: Error decoding rfc3110 key data");
670 return mStatus_NoMemoryErr
;
672 ret
= VerifyData(keyref
, digestStr
, digest
, digestlen
, digestlenAttr
, signature
, siglen
, kSecInputIsDigest
);
676 LogMsg("rsa_sha_verify: Failed for alg %d", ctx
->alg
);
677 return mStatus_BadParamErr
;
681 LogInfo("rsa_sha_verify: Passed for alg %d", ctx
->alg
);
682 return mStatus_NoError
;
685 #endif // TARGET_OS_IPHONE
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
};
691 #ifndef DNSSEC_DISABLED
693 mDNSexport mStatus
DNSSECCryptoInit(mDNS
*const m
)
697 result
= DigestAlgInit(SHA1_DIGEST_TYPE
, &sha_funcs
);
698 if (result
!= mStatus_NoError
)
700 result
= DigestAlgInit(SHA256_DIGEST_TYPE
, &sha_funcs
);
701 if (result
!= mStatus_NoError
)
703 result
= CryptoAlgInit(CRYPTO_RSA_SHA1
, &rsa_sha_funcs
);
704 if (result
!= mStatus_NoError
)
706 result
= CryptoAlgInit(CRYPTO_RSA_NSEC3_SHA1
, &rsa_sha_funcs
);
707 if (result
!= mStatus_NoError
)
709 result
= CryptoAlgInit(CRYPTO_RSA_SHA256
, &rsa_sha_funcs
);
710 if (result
!= mStatus_NoError
)
712 result
= CryptoAlgInit(CRYPTO_RSA_SHA512
, &rsa_sha_funcs
);
713 if (result
!= mStatus_NoError
)
715 result
= EncAlgInit(ENC_BASE32
, &enc_funcs
);
716 if (result
!= mStatus_NoError
)
718 result
= EncAlgInit(ENC_BASE64
, &enc_funcs
);
719 if (result
!= mStatus_NoError
)
722 result
= DNSSECPlatformInit(m
);
727 #else // !DNSSEC_DISABLED
729 mDNSexport mStatus
DNSSECCryptoInit(mDNS
*const m
)
733 return mStatus_NoError
;
736 #endif // !DNSSEC_DISABLED