1/*
2 * Copyright (c) 2012 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24// #define COMMON_DH_FUNCTIONS
25#include "CommonDH.h"
26#include "CommonRandomSPI.h"
27#include <dispatch/dispatch.h>
28#include <dispatch/queue.h>
29#include <corecrypto/ccn.h>
30#include <corecrypto/ccdh.h>
31#include <corecrypto/ccdh_gp.h>
32#include "ccMemory.h"
33#include "ccErrors.h"
34#include "ccGlobals.h"
35#include "ccdebug.h"
36
37typedef struct CCDHParameters_s {
38    ccdh_const_gp_t gp;
39    size_t malloced;
40} CCDHParmSetstruct, *CCDHParmSet;
41
42typedef struct DH_ {
43	CCDHParmSet parms;
44    ccdh_full_ctx_t ctx;
45} CCDHstruct, *CCDH;
46
47
48static void kCCDHRFC2409Group2_storage(void) {}
49static void kCCDHRFC3526Group5_storage(void) {}
50const CCDHParameters kCCDHRFC2409Group2 = (CCDHParameters)&kCCDHRFC2409Group2_storage;
51const CCDHParameters kCCDHRFC3526Group5 = (CCDHParameters)&kCCDHRFC3526Group5_storage;
52
53CCDHRef
54CCDHCreate(CCDHParameters dhParameter)
55{
56    CCDHParmSet CCDHParm = (CCDHParmSet)dhParameter;
57    CCDHParmSet stockParm = NULL;
58    CCDH retval = NULL;
59    size_t retSize = 0;
60
61    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
62    CC_NONULLPARMRETNULL(dhParameter);
63    if (dhParameter == kCCDHRFC2409Group2) {
64        return NULL;
65    } else if (dhParameter == kCCDHRFC3526Group5) {
66        stockParm = CC_XMALLOC(sizeof(CCDHParmSetstruct));
67        stockParm->gp = ccdh_gp_rfc3526group05();
68        stockParm->malloced = true;
69        CCDHParm = stockParm;
70    } else {
71    }
72
73    retval = CC_XMALLOC(sizeof(CCDHstruct));
74    if(retval == NULL) goto error;
75
76    retSize = ccdh_full_ctx_size(ccdh_ccn_size(CCDHParm->gp));
77    retval->ctx._full = CC_XMALLOC(retSize);
78
79    if(retval->ctx._full == NULL) goto error;
80    ccdh_ctx_init(CCDHParm->gp, retval->ctx);
81    retval->parms = CCDHParm;
82
83    return (CCDHRef) retval;
84
85error:
86    if(stockParm) CC_XFREE(stockParm, sizeof(CCDHParmSetstruct));
87    if(retval) CC_XFREE(retval, retSize);
88    return NULL;
89}
90
91void
92CCDHRelease(CCDHRef ref)
93{
94    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
95    if(ref == NULL) return;
96    CCDH keyref = (CCDH) ref;
97    if(keyref->ctx._full)
98        CC_XFREE(keyref->ctx._full, ccdh_full_ctx_size(ccdh_ccn_size(keyref->parms->gp)));
99    keyref->ctx._full = NULL;
100    keyref->parms = NULL;
101    CC_XFREE(keyref, sizeof(CCDHstruct));
102}
103
104int
105CCDHGenerateKey(CCDHRef ref, void *output, size_t *outputLength)
106{
107    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
108    CC_NONULLPARM(ref);
109    CC_NONULLPARM(output);
110    CC_NONULLPARM(outputLength);
111
112    CCDH keyref = (CCDH) ref;
113
114    if(ccdh_generate_key(keyref->parms->gp, ccDRBGGetRngState(), keyref->ctx.pub))
115        return -1;
116
117    size_t size_needed = ccdh_export_pub_size(keyref->ctx);
118    if(size_needed > *outputLength) {
119        *outputLength = size_needed;
120        return -1;
121    }
122
123    *outputLength = size_needed;
124    ccdh_export_pub(keyref->ctx, output);
125    return 0;
126}
127
128
129int
130CCDHComputeKey(unsigned char *sharedKey, size_t *sharedKeyLen, const void *peerPubKey, size_t peerPubKeyLen, CCDHRef ref)
131{
132    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
133    CC_NONULLPARM(sharedKey);
134    CC_NONULLPARM(sharedKeyLen);
135    CC_NONULLPARM(peerPubKey);
136    CC_NONULLPARM(ref);
137
138    CCDH keyref = (CCDH) ref;
139    ccdh_pub_ctx_decl_gp(keyref->parms->gp, peer_pub);
140    cc_size n = ccdh_ctx_n(keyref->ctx);
141    cc_unit skey[n];
142
143    if(ccdh_import_pub(keyref->parms->gp, peerPubKeyLen, peerPubKey,
144                    peer_pub))
145        return -1;
146
147    if(ccdh_compute_key(keyref->ctx, peer_pub, skey))
148        return -1;
149
150    size_t size_needed = ccn_write_uint_size(n, skey);
151    if(size_needed > *sharedKeyLen) {
152        *sharedKeyLen = size_needed;
153        return -1;
154    }
155    *sharedKeyLen = size_needed;
156    (void) ccn_write_uint_padded(n, skey, *sharedKeyLen, sharedKey);
157
158    return 0;
159
160}
161
162CCDHParameters
163CCDHParametersCreateFromData(const void *p, size_t pLen, const void *g, size_t gLen, size_t l)
164{
165    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
166    CC_NONULLPARMRETNULL(p);
167    CC_NONULLPARMRETNULL(g);
168
169    cc_size psize = ccn_nof_size(pLen);
170    cc_size gsize = ccn_nof_size(gLen);
171    cc_size n = (psize > gsize) ? psize: gsize;
172    cc_unit pval[n], gval[n];
173
174    CCDHParmSet retval = CC_XMALLOC(sizeof(CCDHParmSetstruct));
175    if(!retval) goto error;
176
177    retval->malloced = ccdh_gp_size(n);
178    retval->gp.gp = (ccdh_gp *) CC_XMALLOC(retval->malloced);
179    if(!retval->gp.gp) goto error;
180    if(ccdh_init_gp(retval->gp._ncgp, n, pval, gval, (cc_size) l))
181        goto error;
182    return retval;
183error:
184    if(retval && retval->gp.gp) CC_XFREE((ccdh_gp *) retval->gp.gp, retval->malloced);
185    if(retval) CC_XFREE(retval, sizeof(CCDHParmSetstruct));
186    return NULL;
187}
188
189void
190CCDHParametersRelease(CCDHParameters parameters)
191{
192    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
193    if(parameters == NULL) return;
194    if(parameters == kCCDHRFC2409Group2) return;
195    if(parameters == kCCDHRFC3526Group5) return;
196
197    CCDHParmSet CCDHParm = (CCDHParmSet) parameters;
198    if(CCDHParm->malloced) {
199        CC_XFREE((void *) parameters->gp.gp, retval->malloced);
200    }
201    CCDHParm->malloced = 0;
202    CCDHParm->gp.gp = NULL;
203    CC_XFREE(CCDHParm, sizeof(CCDHParmSetstruct));
204}
205
206// TODO - needs PKCS3 in/out
207CCDHParameters
208CCDHParametersCreateFromPKCS3(const void *data, size_t len)
209{
210    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
211    CC_NONULLPARMRETNULL(data);
212    return NULL;
213}
214
215size_t
216CCDHParametersPKCS3EncodeLength(CCDHParameters parms)
217{
218    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
219    return 0;
220}
221
222size_t
223CCDHParametersPKCS3Encode(CCDHParameters parms, void *data, size_t dataAvailable)
224{
225    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
226    return 0;
227}
228
229