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
28AlgFuncs *DigestAlgFuncs[DIGEST_TYPE_MAX];
29AlgFuncs *CryptoAlgFuncs[CRYPTO_ALG_MAX];
30AlgFuncs *EncAlgFuncs[ENC_ALG_MAX];
31
32mDNSexport 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
51mDNSexport 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
71mDNSexport 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
91mDNSexport 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
137mDNSexport 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
162mDNSexport 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
186mDNSexport 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
210mDNSexport 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
234mDNSexport 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
258mDNSexport 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