1 /* -*- Mode: C; tab-width: 4 -*-
2  *
3  * Copyright (c) 2011-2012 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 // CryptoAlg.c:
20 // Interface to DNSSEC cryptographic algorithms. The crypto support itself is
21 // provided by the platform and the functions in this file just provide an
22 // interface to access them in a more generic way.
23 // ***************************************************************************
24 
25 #include "mDNSEmbeddedAPI.h"
26 #include "CryptoAlg.h"
27 
28 AlgFuncs *DigestAlgFuncs[DIGEST_TYPE_MAX];
29 AlgFuncs *CryptoAlgFuncs[CRYPTO_ALG_MAX];
30 AlgFuncs *EncAlgFuncs[ENC_ALG_MAX];
31 
DigestAlgInit(mDNSu8 digestType,AlgFuncs * func)32 mDNSexport mStatus DigestAlgInit(mDNSu8 digestType, AlgFuncs *func)
33 {
34     if (digestType >= DIGEST_TYPE_MAX)
35     {
36         LogMsg("DigestAlgInit: digestType %d exceeds bounds", digestType);
37         return mStatus_BadParamErr;
38     }
39     // As digestTypes may not be consecutive, check for specific digest types
40     // that we support
41     if (digestType != SHA1_DIGEST_TYPE &&
42         digestType != SHA256_DIGEST_TYPE)
43     {
44         LogMsg("DigestAlgInit: digestType %d not supported", digestType);
45         return mStatus_BadParamErr;
46     }
47     DigestAlgFuncs[digestType] = func;
48     return mStatus_NoError;
49 }
50 
CryptoAlgInit(mDNSu8 alg,AlgFuncs * func)51 mDNSexport mStatus CryptoAlgInit(mDNSu8 alg, AlgFuncs *func)
52 {
53     if (alg >= CRYPTO_ALG_MAX)
54     {
55         LogMsg("CryptoAlgInit: alg %d exceeds bounds", alg);
56         return mStatus_BadParamErr;
57     }
58     // As algs may not be consecutive, check for specific algorithms
59     // that we support
60     if (alg != CRYPTO_RSA_SHA1 && alg != CRYPTO_RSA_SHA256 && alg != CRYPTO_RSA_SHA512 &&
61         alg != CRYPTO_DSA_NSEC3_SHA1 && alg != CRYPTO_RSA_NSEC3_SHA1)
62     {
63         LogMsg("CryptoAlgInit: alg %d not supported", alg);
64         return mStatus_BadParamErr;
65     }
66 
67     CryptoAlgFuncs[alg] = func;
68     return mStatus_NoError;
69 }
70 
EncAlgInit(mDNSu8 alg,AlgFuncs * func)71 mDNSexport mStatus EncAlgInit(mDNSu8 alg, AlgFuncs *func)
72 {
73     if (alg >= ENC_ALG_MAX)
74     {
75         LogMsg("EncAlgInit: alg %d exceeds bounds", alg);
76         return mStatus_BadParamErr;
77     }
78 
79     // As algs may not be consecutive, check for specific algorithms
80     // that we support
81     if (alg != ENC_BASE32 && alg != ENC_BASE64)
82     {
83         LogMsg("EncAlgInit: alg %d not supported", alg);
84         return mStatus_BadParamErr;
85     }
86 
87     EncAlgFuncs[alg] = func;
88     return mStatus_NoError;
89 }
90 
AlgCreate(AlgType type,mDNSu8 alg)91 mDNSexport AlgContext *AlgCreate(AlgType type, mDNSu8 alg)
92 {
93     AlgFuncs *func = mDNSNULL;
94     AlgContext *ctx;
95 
96     if (type == CRYPTO_ALG)
97     {
98         if (alg >= CRYPTO_ALG_MAX) return mDNSNULL;
99         func = CryptoAlgFuncs[alg];
100     }
101     else if (type == DIGEST_ALG)
102     {
103         if (alg >= DIGEST_TYPE_MAX) return mDNSNULL;
104         func = DigestAlgFuncs[alg];
105     }
106     else if (type == ENC_ALG)
107     {
108         if (alg >= ENC_ALG_MAX) return mDNSNULL;
109         func = EncAlgFuncs[alg];
110     }
111 
112     if (!func)
113     {
114         // If there is no support from the platform, this case can happen.
115         LogInfo("AlgCreate: func is NULL");
116         return mDNSNULL;
117     }
118 
119     if (func->Create)
120     {
121         mStatus err;
122         ctx = mDNSPlatformMemAllocate(sizeof(AlgContext));
123         if (!ctx) return mDNSNULL;
124         // Create expects ctx->alg to be initialized
125         ctx->alg = alg;
126         err = func->Create(ctx);
127         if (err == mStatus_NoError)
128         {
129             ctx->type = type;
130             return ctx;
131         }
132         mDNSPlatformMemFree(ctx);
133     }
134     return mDNSNULL;
135 }
136 
AlgDestroy(AlgContext * ctx)137 mDNSexport mStatus AlgDestroy(AlgContext *ctx)
138 {
139     AlgFuncs *func = mDNSNULL;
140 
141     if (ctx->type == CRYPTO_ALG)
142         func = CryptoAlgFuncs[ctx->alg];
143     else if (ctx->type == DIGEST_ALG)
144         func = DigestAlgFuncs[ctx->alg];
145     else if (ctx->type == ENC_ALG)
146         func = EncAlgFuncs[ctx->alg];
147 
148     if (!func)
149     {
150         LogMsg("AlgDestroy: ERROR!! func is NULL");
151         mDNSPlatformMemFree(ctx);
152         return mStatus_BadParamErr;
153     }
154 
155     if (func->Destroy)
156         func->Destroy(ctx);
157 
158     mDNSPlatformMemFree(ctx);
159     return mStatus_NoError;
160 }
161 
AlgLength(AlgContext * ctx)162 mDNSexport mDNSu32 AlgLength(AlgContext *ctx)
163 {
164     AlgFuncs *func = mDNSNULL;
165 
166     if (ctx->type == CRYPTO_ALG)
167         func = CryptoAlgFuncs[ctx->alg];
168     else if (ctx->type == DIGEST_ALG)
169         func = DigestAlgFuncs[ctx->alg];
170     else if (ctx->type == ENC_ALG)
171         func = EncAlgFuncs[ctx->alg];
172 
173     // This should never happen as AlgCreate would have failed
174     if (!func)
175     {
176         LogMsg("AlgLength: ERROR!! func is NULL");
177         return 0;
178     }
179 
180     if (func->Length)
181         return (func->Length(ctx));
182     else
183         return 0;
184 }
185 
AlgAdd(AlgContext * ctx,const void * data,mDNSu32 len)186 mDNSexport mStatus AlgAdd(AlgContext *ctx, const void *data, mDNSu32 len)
187 {
188     AlgFuncs *func = mDNSNULL;
189 
190     if (ctx->type == CRYPTO_ALG)
191         func = CryptoAlgFuncs[ctx->alg];
192     else if (ctx->type == DIGEST_ALG)
193         func = DigestAlgFuncs[ctx->alg];
194     else if (ctx->type == ENC_ALG)
195         func = EncAlgFuncs[ctx->alg];
196 
197     // This should never happen as AlgCreate would have failed
198     if (!func)
199     {
200         LogMsg("AlgAdd: ERROR!! func is NULL");
201         return mStatus_BadParamErr;
202     }
203 
204     if (func->Add)
205         return (func->Add(ctx, data, len));
206     else
207         return mStatus_BadParamErr;
208 }
209 
AlgVerify(AlgContext * ctx,mDNSu8 * key,mDNSu32 keylen,mDNSu8 * signature,mDNSu32 siglen)210 mDNSexport mStatus AlgVerify(AlgContext *ctx, mDNSu8 *key, mDNSu32 keylen, mDNSu8 *signature, mDNSu32 siglen)
211 {
212     AlgFuncs *func = mDNSNULL;
213 
214     if (ctx->type == CRYPTO_ALG)
215         func = CryptoAlgFuncs[ctx->alg];
216     else if (ctx->type == DIGEST_ALG)
217         func = DigestAlgFuncs[ctx->alg];
218     else if (ctx->type == ENC_ALG)
219         func = EncAlgFuncs[ctx->alg];
220 
221     // This should never happen as AlgCreate would have failed
222     if (!func)
223     {
224         LogMsg("AlgVerify: ERROR!! func is NULL");
225         return mStatus_BadParamErr;
226     }
227 
228     if (func->Verify)
229         return (func->Verify(ctx, key, keylen, signature, siglen));
230     else
231         return mStatus_BadParamErr;
232 }
233 
AlgEncode(AlgContext * ctx)234 mDNSexport mDNSu8* AlgEncode(AlgContext *ctx)
235 {
236     AlgFuncs *func = mDNSNULL;
237 
238     if (ctx->type == CRYPTO_ALG)
239         func = CryptoAlgFuncs[ctx->alg];
240     else if (ctx->type == DIGEST_ALG)
241         func = DigestAlgFuncs[ctx->alg];
242     else if (ctx->type == ENC_ALG)
243         func = EncAlgFuncs[ctx->alg];
244 
245     // This should never happen as AlgCreate would have failed
246     if (!func)
247     {
248         LogMsg("AlgEncode: ERROR!! func is NULL");
249         return mDNSNULL;
250     }
251 
252     if (func->Encode)
253         return (func->Encode(ctx));
254     else
255         return mDNSNULL;
256 }
257 
AlgFinal(AlgContext * ctx,void * data,mDNSu32 len)258 mDNSexport mStatus AlgFinal(AlgContext *ctx, void *data, mDNSu32 len)
259 {
260     AlgFuncs *func = mDNSNULL;
261 
262     if (ctx->type == CRYPTO_ALG)
263         func = CryptoAlgFuncs[ctx->alg];
264     else if (ctx->type == DIGEST_ALG)
265         func = DigestAlgFuncs[ctx->alg];
266     else if (ctx->type == ENC_ALG)
267         func = EncAlgFuncs[ctx->alg];
268 
269     // This should never happen as AlgCreate would have failed
270     if (!func)
271     {
272         LogMsg("AlgEncode: ERROR!! func is NULL");
273         return mDNSNULL;
274     }
275 
276     if (func->Final)
277         return (func->Final(ctx, data, len));
278     else
279         return mStatus_BadParamErr;
280 }
281