1/* 2 * Copyright (c) 2011-12 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/* 25 * Copyright (c) 2006 Kungliga Tekniska Högskolan 26 * (Royal Institute of Technology, Stockholm, Sweden). 27 * All rights reserved. 28 * 29 * Portions Copyright (c) 2010 Apple Inc. All rights reserved. 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions 33 * are met: 34 * 35 * 1. Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 42 * 3. Neither the name of the Institute nor the names of its contributors 43 * may be used to endorse or promote products derived from this software 44 * without specific prior written permission. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 49 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 56 * SUCH DAMAGE. 57 */ 58 59#include "ossl-config.h" 60 61#ifdef HAVE_CDSA 62 63#include <stdio.h> 64#include <stdlib.h> 65 66#include "ossl-common.h" 67#include "ossl-dh.h" 68 69#include "rfc2459_asn1.h" 70 71 72 73struct dh_cdsa { 74 CSSM_KEY priv_key; 75 CSSM_KEY pub_key; 76}; 77 78/* 79 * shims for CSSM/CDSA DH 80 */ 81static int 82dh_generate_key(DH *dh) 83{ 84 CSSM_CSP_HANDLE cspHandle = _cs_get_cdsa_csphandle(); 85 struct dh_cdsa *cdsa = DH_get_ex_data(dh, 0); 86 uint32_t pubAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_DATA; 87 uint32_t privAttr = CSSM_KEYATTR_RETURN_REF; 88 DHParameter dp; 89 CSSM_CC_HANDLE handle; 90 CSSM_DATA param; 91 CSSM_RETURN ret; 92 size_t size; 93 94 if ((dh->p == NULL) || (dh->g == NULL)) { 95 return (0); 96 } 97 98 CSSM_FreeKey(cspHandle, NULL, &cdsa->pub_key, CSSM_FALSE); 99 CSSM_FreeKey(cspHandle, NULL, &cdsa->priv_key, CSSM_FALSE); 100 101 memset(&dp, 0, sizeof(dp)); 102 103 ret = _cs_BN_to_integer(dh->p, &dp.prime); 104 if (ret == 0) { 105 ret = _cs_BN_to_integer(dh->g, &dp.base); 106 } 107 if (ret) { 108 free_DHParameter(&dp); 109 return (0); 110 } 111 dp.privateValueLength = NULL; 112 113 ASN1_MALLOC_ENCODE(DHParameter, param.Data, param.Length, 114 &dp, &size, ret); 115 free_DHParameter(&dp); 116 if (ret) { 117 return (0); 118 } 119 if (size != param.Length) { 120 abort(); 121 } 122 123 ret = CSSM_CSP_CreateKeyGenContext(cspHandle, 124 CSSM_ALGID_DH, 125 BN_num_bits(dh->p) - 1, 126 NULL, 127 NULL, 128 NULL, 129 NULL, 130 ¶m, 131 &handle); 132 free(param.Data); 133 if (ret) { 134 return (0); 135 } 136 137 ret = CSSM_GenerateKeyPair(handle, 138 /* pubkey */ 139 CSSM_KEYUSE_DERIVE, 140 pubAttr, 141 &_cs_labelData, 142 &cdsa->pub_key, 143 /* private key */ 144 CSSM_KEYUSE_DERIVE, 145 privAttr, 146 &_cs_labelData, 147 NULL, 148 &cdsa->priv_key); 149 150 CSSM_DeleteContext(handle); 151 if (ret) { 152 return (0); 153 } 154 155 dh->pub_key = BN_bin2bn(cdsa->pub_key.KeyData.Data, cdsa->pub_key.KeyData.Length, NULL); 156 if (dh->pub_key == NULL) { 157 return (0); 158 } 159 160 dh->priv_key = BN_bin2bn(cdsa->priv_key.KeyData.Data, cdsa->priv_key.KeyData.Length, NULL); 161 if (dh->priv_key == NULL) { 162 return (0); 163 } 164 165 return (1); 166} 167 168 169static int 170dh_compute_key(unsigned char *shared, const BIGNUM *pub, DH *dh) 171{ 172 CSSM_CSP_HANDLE cspHandle = _cs_get_cdsa_csphandle(); 173 struct dh_cdsa *cdsa = DH_get_ex_data(dh, 0); 174 CSSM_ACCESS_CREDENTIALS creds; 175 CSSM_CC_HANDLE handle; 176 CSSM_KEY derivedKey; 177 CSSM_DATA param; 178 CSSM_RETURN ret; 179 int sharedlen = -1; 180 181 memset(&creds, 0, sizeof(creds)); 182 memset(&derivedKey, 0, sizeof(derivedKey)); 183 184 ret = CSSM_CSP_CreateDeriveKeyContext(cspHandle, 185 CSSM_ALGID_DH, 186 CSSM_ALGID_RC5, /* will give us plenty of bits */ 187 DH_size(dh) * 8, /* size in bits */ 188 &creds, 189 &cdsa->priv_key, 190 0, 191 0, 192 0, 193 &handle); 194 if (ret) { 195 return (-1); 196 } 197 198 param.Length = BN_num_bytes(pub); 199 param.Data = malloc(param.Length); 200 if (param.Data == NULL) { 201 CSSM_DeleteContext(handle); 202 return (-1); 203 } 204 BN_bn2bin(pub, param.Data); 205 206 ret = CSSM_DeriveKey(handle, 207 ¶m, 208 CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, 209 CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, 210 &_cs_labelData, 211 NULL, 212 &derivedKey); 213 free(param.Data); 214 if (ret) { 215 /* cssmPerror("CSSM_DeriveKey", ret); */ 216 return (-1); 217 } 218 219 memcpy(shared, derivedKey.KeyData.Data, derivedKey.KeyData.Length); 220 if (derivedKey.KeyData.Length > DH_size(dh)) { 221 CSSM_FreeKey(cspHandle, NULL, &derivedKey, CSSM_FALSE); 222 CSSM_DeleteContext(handle); 223 return (-1); 224 } 225 226 sharedlen = derivedKey.KeyData.Length; 227 228 CSSM_FreeKey(cspHandle, NULL, &derivedKey, CSSM_FALSE); 229 CSSM_DeleteContext(handle); 230 231 return (sharedlen); 232} 233 234 235static int 236dh_generate_params(DH *dh, int a, int b, BN_GENCB *callback) 237{ 238 /* groups should already be known, we don't care about this */ 239 return (0); 240} 241 242 243static int 244dh_init(DH *dh) 245{ 246 struct dh_cdsa *cdsa; 247 248 cdsa = calloc(1, sizeof(*cdsa)); 249 if (cdsa == NULL) { 250 return (0); 251 } 252 253 DH_set_ex_data(dh, 0, cdsa); 254 255 return (1); 256} 257 258 259static int 260dh_finish(DH *dh) 261{ 262 struct dh_cdsa *cdsa = DH_get_ex_data(dh, 0); 263 264 if (cdsa) { 265 CSSM_CSP_HANDLE cspHandle = _cs_get_cdsa_csphandle(); 266 267 CSSM_FreeKey(cspHandle, NULL, &cdsa->pub_key, CSSM_FALSE); 268 CSSM_FreeKey(cspHandle, NULL, &cdsa->priv_key, CSSM_FALSE); 269 free(cdsa); 270 } 271 return (1); 272} 273 274 275/* 276 * 277 */ 278 279const DH_METHOD _ossl_dh_cdsa_method = 280{ 281 .name = "cryptoshim cdsa DH", 282 .generate_key = dh_generate_key, 283 .compute_key = dh_compute_key, 284 .bn_mod_exp = NULL, 285 .init = dh_init, 286 .finish = dh_finish, 287 .flags = 0, 288 .app_data = NULL, 289 .generate_params = dh_generate_params 290}; 291 292#endif /* HAVE_CDSA */ 293 294/** 295 * DH implementation using cdsa. 296 * 297 * @return the DH_METHOD for the DH implementation using libcdsa. 298 * 299 * @ingroup hcrypto_dh 300 */ 301const DH_METHOD * 302DH_cdsa_method(void) 303{ 304#ifdef HAVE_CDSA 305 return (&_ossl_dh_cdsa_method); 306 307#else 308 return (NULL); 309#endif /* HAVE_CDSA */ 310} 311