source: rtems-libbsd/mDNSResponder/mDNSMacOSX/CryptoSupport.c @ 4a5f546

55-freebsd-126-freebsd-12
Last change on this file since 4a5f546 was f761b29, checked in by Sebastian Huber <sebastian.huber@…>, on 09/19/18 at 06:52:21

mDNSResponder: Update to v625.41.2

The sources can be obtained via:

https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-625.41.2.tar.gz

Update #3522.

  • Property mode set to 100644
File size: 22.6 KB
Line 
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
39mDNSlocal SecKeyRef SecKeyCreateRSAPublicKey_OSX(unsigned char *asn1, int length);
40#endif
41
42typedef struct
43{
44    dispatch_data_t encData;
45    dispatch_data_t encMap;
46    dispatch_data_t encNULL;
47}encContext;
48
49mDNSlocal 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
78mDNSlocal 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
88mDNSlocal 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
120mDNSlocal 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
158mDNSlocal 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
181mDNSlocal mStatus sha_destroy(AlgContext *ctx)
182{
183    mDNSPlatformMemFree(ctx->context);
184    return mStatus_NoError;
185}
186
187mDNSlocal 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
201mDNSlocal 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
218mDNSlocal 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
250mDNSlocal 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
278mDNSlocal 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
307mDNSlocal mStatus rsa_sha_destroy(AlgContext *ctx)
308{
309    mDNSPlatformMemFree(ctx->context);
310    return mStatus_NoError;
311}
312
313mDNSlocal 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
330mDNSlocal 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
351mDNSlocal 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
501mDNSlocal 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
553mDNSlocal 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
587mDNSlocal 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;
668err:
669    CFRelease(verifyXForm);
670    return false;
671}
672
673mDNSlocal 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
729AlgFuncs sha_funcs = {sha_create, sha_destroy, sha_len, sha_add, sha_verify, mDNSNULL, sha_final};
730AlgFuncs rsa_sha_funcs = {rsa_sha_create, rsa_sha_destroy, rsa_sha_len, rsa_sha_add, rsa_sha_verify, mDNSNULL, mDNSNULL};
731AlgFuncs enc_funcs = {enc_create, enc_destroy, mDNSNULL, enc_add, mDNSNULL, enc_encode, mDNSNULL};
732
733#ifndef DNSSEC_DISABLED
734
735mDNSexport 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
771mDNSexport mStatus DNSSECCryptoInit(mDNS *const m)
772{
773    (void) m;
774   
775    return mStatus_NoError;
776}
777
778#endif // !DNSSEC_DISABLED
779
780
Note: See TracBrowser for help on using the repository browser.