1 /* $NetBSD: dh-ltm.c,v 1.1.1.2 2014/04/24 12:45:30 pettai Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * 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 #ifdef HAVE_CONFIG_H 37 #include <config.h> 38 #endif 39 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <dh.h> 43 44 #include <krb5/roken.h> 45 46 #include "tommath.h" 47 48 static void 49 BN2mpz(mp_int *s, const BIGNUM *bn) 50 { 51 size_t len; 52 void *p; 53 54 len = BN_num_bytes(bn); 55 p = malloc(len); 56 BN_bn2bin(bn, p); 57 mp_read_unsigned_bin(s, p, len); 58 free(p); 59 } 60 61 62 static BIGNUM * 63 mpz2BN(mp_int *s) 64 { 65 size_t size; 66 BIGNUM *bn; 67 void *p; 68 69 size = mp_unsigned_bin_size(s); 70 p = malloc(size); 71 if (p == NULL && size != 0) 72 return NULL; 73 mp_to_unsigned_bin(s, p); 74 75 bn = BN_bin2bn(p, size, NULL); 76 free(p); 77 return bn; 78 } 79 80 /* 81 * 82 */ 83 84 #define DH_NUM_TRIES 10 85 86 static int 87 ltm_dh_generate_key(DH *dh) 88 { 89 mp_int pub, priv_key, g, p; 90 int have_private_key = (dh->priv_key != NULL); 91 int codes, times = 0; 92 int res; 93 94 if (dh->p == NULL || dh->g == NULL) 95 return 0; 96 97 while (times++ < DH_NUM_TRIES) { 98 if (!have_private_key) { 99 size_t bits = BN_num_bits(dh->p); 100 101 if (dh->priv_key) 102 BN_free(dh->priv_key); 103 104 dh->priv_key = BN_new(); 105 if (dh->priv_key == NULL) 106 return 0; 107 if (!BN_rand(dh->priv_key, bits - 1, 0, 0)) { 108 BN_clear_free(dh->priv_key); 109 dh->priv_key = NULL; 110 return 0; 111 } 112 } 113 if (dh->pub_key) 114 BN_free(dh->pub_key); 115 116 mp_init_multi(&pub, &priv_key, &g, &p, NULL); 117 118 BN2mpz(&priv_key, dh->priv_key); 119 BN2mpz(&g, dh->g); 120 BN2mpz(&p, dh->p); 121 122 res = mp_exptmod(&g, &priv_key, &p, &pub); 123 124 mp_clear_multi(&priv_key, &g, &p, NULL); 125 if (res != 0) 126 continue; 127 128 dh->pub_key = mpz2BN(&pub); 129 mp_clear(&pub); 130 if (dh->pub_key == NULL) 131 return 0; 132 133 if (DH_check_pubkey(dh, dh->pub_key, &codes) && codes == 0) 134 break; 135 if (have_private_key) 136 return 0; 137 } 138 139 if (times >= DH_NUM_TRIES) { 140 if (!have_private_key && dh->priv_key) { 141 BN_free(dh->priv_key); 142 dh->priv_key = NULL; 143 } 144 if (dh->pub_key) { 145 BN_free(dh->pub_key); 146 dh->pub_key = NULL; 147 } 148 return 0; 149 } 150 151 return 1; 152 } 153 154 static int 155 ltm_dh_compute_key(unsigned char *shared, const BIGNUM * pub, DH *dh) 156 { 157 mp_int s, priv_key, p, peer_pub; 158 int ret; 159 160 if (dh->pub_key == NULL || dh->g == NULL || dh->priv_key == NULL) 161 return -1; 162 163 mp_init_multi(&s, &priv_key, &p, &peer_pub, NULL); 164 BN2mpz(&p, dh->p); 165 BN2mpz(&peer_pub, pub); 166 167 /* check if peers pubkey is reasonable */ 168 if (mp_isneg(&peer_pub) 169 || mp_cmp(&peer_pub, &p) >= 0 170 || mp_cmp_d(&peer_pub, 1) <= 0) 171 { 172 ret = -1; 173 goto out; 174 } 175 176 BN2mpz(&priv_key, dh->priv_key); 177 178 ret = mp_exptmod(&peer_pub, &priv_key, &p, &s); 179 180 if (ret != 0) { 181 ret = -1; 182 goto out; 183 } 184 185 ret = mp_unsigned_bin_size(&s); 186 mp_to_unsigned_bin(&s, shared); 187 188 out: 189 mp_clear_multi(&s, &priv_key, &p, &peer_pub, NULL); 190 191 return ret; 192 } 193 194 static int 195 ltm_dh_generate_params(DH *dh, int a, int b, BN_GENCB *callback) 196 { 197 /* groups should already be known, we don't care about this */ 198 return 0; 199 } 200 201 static int 202 ltm_dh_init(DH *dh) 203 { 204 return 1; 205 } 206 207 static int 208 ltm_dh_finish(DH *dh) 209 { 210 return 1; 211 } 212 213 214 /* 215 * 216 */ 217 218 const DH_METHOD _hc_dh_ltm_method = { 219 "hcrypto ltm DH", 220 ltm_dh_generate_key, 221 ltm_dh_compute_key, 222 NULL, 223 ltm_dh_init, 224 ltm_dh_finish, 225 0, 226 NULL, 227 ltm_dh_generate_params 228 }; 229 230 /** 231 * DH implementation using libtommath. 232 * 233 * @return the DH_METHOD for the DH implementation using libtommath. 234 * 235 * @ingroup hcrypto_dh 236 */ 237 238 const DH_METHOD * 239 DH_ltm_method(void) 240 { 241 return &_hc_dh_ltm_method; 242 } 243