1/*
2 * Copyright (c) 2006 - 2010 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the Institute nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include <config.h>
37
38#ifdef HEIM_HC_SF
39
40#include <stdio.h>
41#include <stdlib.h>
42#include <dh.h>
43
44#include <roken.h>
45
46#include <rfc2459_asn1.h>
47
48#include <Security/SecDH.h>
49
50#include "common.h"
51
52struct dh_sf {
53    SecDHContext secdh;
54};
55
56#define DH_NUM_TRIES 10
57
58static int
59sf_dh_generate_key(DH *dh)
60{
61    struct dh_sf *sf = DH_get_ex_data(dh, 0);
62    size_t length, size;
63    DHParameter dp;
64    void *data = NULL;
65    int ret;
66
67    if (dh->p == NULL || dh->g == NULL)
68	return 0;
69
70    memset(&dp, 0, sizeof(dp));
71
72    ret = _hc_BN_to_integer(dh->p, &dp.prime);
73    if (ret == 0)
74	ret = _hc_BN_to_integer(dh->g, &dp.base);
75    if (ret) {
76	free_DHParameter(&dp);
77	return 0;
78    }
79    dp.privateValueLength = NULL;
80
81    ASN1_MALLOC_ENCODE(DHParameter, data, length, &dp, &size, ret);
82    free_DHParameter(&dp);
83    if (ret)
84	return 0;
85    if (size != length)
86	abort();
87
88    if (sf->secdh) {
89	SecDHDestroy(sf->secdh);
90	sf->secdh = NULL;
91    }
92
93    ret = SecDHCreateFromParameters(data, length, &sf->secdh);
94    if (ret)
95	goto error;
96
97    free(data);
98    data = NULL;
99
100    length = BN_num_bytes(dh->p);
101    data = malloc(size);
102    if (data == NULL)
103	goto error;
104
105    ret = SecDHGenerateKeypair(sf->secdh, data, &length);
106    if (ret)
107	goto error;
108
109    dh->pub_key = BN_bin2bn(data, length, NULL);
110    if (dh->pub_key == NULL)
111	goto error;
112
113    free(data);
114
115    return 1;
116
117 error:
118    if (data)
119	free(data);
120    if (sf->secdh)
121	SecDHDestroy(sf->secdh);
122    sf->secdh = NULL;
123
124    return 1;
125}
126
127static int
128sf_dh_compute_key(unsigned char *shared, const BIGNUM * pub, DH *dh)
129{
130    struct dh_sf *sf = DH_get_ex_data(dh, 0);
131    size_t length, shared_length;
132    OSStatus ret;
133    void *data;
134
135    shared_length = BN_num_bytes(dh->p);
136
137    length = BN_num_bytes(pub);
138    data = malloc(length);
139    if (data == NULL)
140	return 0;
141
142    BN_bn2bin(pub, data);
143
144    ret = SecDHComputeKey(sf->secdh, data, length, shared, &shared_length);
145    free(data);
146    if (ret)
147	return 0;
148
149    return shared_length;
150}
151
152
153static int
154sf_dh_generate_params(DH *dh, int a, int b, BN_GENCB *callback)
155{
156    return 0;
157}
158
159static int
160sf_dh_init(DH *dh)
161{
162    struct dh_sf *sf;
163
164    sf = calloc(1, sizeof(*sf));
165    if (sf == NULL)
166	return 0;
167
168    DH_set_ex_data(dh, 0, sf);
169
170    return 1;
171}
172
173static int
174sf_dh_finish(DH *dh)
175{
176    struct dh_sf *sf = DH_get_ex_data(dh, 0);
177
178    if (sf->secdh)
179	SecDHDestroy(sf->secdh);
180    free(sf);
181
182    return 1;
183}
184
185
186/*
187 *
188 */
189
190const DH_METHOD _hc_dh_sf_method = {
191    "hcrypto sf DH",
192    sf_dh_generate_key,
193    sf_dh_compute_key,
194    NULL,
195    sf_dh_init,
196    sf_dh_finish,
197    0,
198    NULL,
199    sf_dh_generate_params
200};
201
202/**
203 * DH implementation using SecurityFramework
204 *
205 * @return the DH_METHOD for the DH implementation using SecurityFramework.
206 *
207 * @ingroup hcrypto_dh
208 */
209
210const DH_METHOD *
211DH_sf_method(void)
212{
213    return &_hc_dh_sf_method;
214}
215#endif /* HEIM_HC_SF */
216