1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* 3 * COPYRIGHT (C) 2006,2007 4 * THE REGENTS OF THE UNIVERSITY OF MICHIGAN 5 * ALL RIGHTS RESERVED 6 * 7 * Permission is granted to use, copy, create derivative works 8 * and redistribute this software and such derivative works 9 * for any purpose, so long as the name of The University of 10 * Michigan is not used in any advertising or publicity 11 * pertaining to the use of distribution of this software 12 * without specific, written prior authorization. If the 13 * above copyright notice or any other identification of the 14 * University of Michigan is included in any copy of any 15 * portion of this software, then the disclaimer below must 16 * also be included. 17 * 18 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION 19 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY 20 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF 21 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING 22 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 24 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE 25 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR 26 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING 27 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN 28 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGES. 30 */ 31 32 #include "pkinit.h" 33 34 #define FAKECERT 35 36 const krb5_data dh_oid = { 0, 7, "\x2A\x86\x48\xce\x3e\x02\x01" }; 37 38 39 krb5_error_code 40 pkinit_init_req_opts(pkinit_req_opts **reqopts) 41 { 42 krb5_error_code retval = ENOMEM; 43 pkinit_req_opts *opts = NULL; 44 45 *reqopts = NULL; 46 opts = calloc(1, sizeof(*opts)); 47 if (opts == NULL) 48 return retval; 49 50 opts->require_eku = 1; 51 opts->accept_secondary_eku = 0; 52 opts->allow_upn = 0; 53 opts->dh_or_rsa = DH_PROTOCOL; 54 opts->require_crl_checking = 0; 55 opts->dh_size = PKINIT_DEFAULT_DH_MIN_BITS; 56 57 *reqopts = opts; 58 59 return 0; 60 } 61 62 void 63 pkinit_fini_req_opts(pkinit_req_opts *opts) 64 { 65 free(opts); 66 return; 67 } 68 69 krb5_error_code 70 pkinit_init_plg_opts(pkinit_plg_opts **plgopts) 71 { 72 krb5_error_code retval = ENOMEM; 73 pkinit_plg_opts *opts = NULL; 74 75 *plgopts = NULL; 76 opts = calloc(1, sizeof(pkinit_plg_opts)); 77 if (opts == NULL) 78 return retval; 79 80 opts->require_eku = 1; 81 opts->accept_secondary_eku = 0; 82 opts->dh_or_rsa = DH_PROTOCOL; 83 opts->allow_upn = 0; 84 opts->require_crl_checking = 0; 85 opts->require_freshness = 0; 86 opts->disable_freshness = 0; 87 88 opts->dh_min_bits = PKINIT_DEFAULT_DH_MIN_BITS; 89 90 *plgopts = opts; 91 92 return 0; 93 } 94 95 void 96 pkinit_fini_plg_opts(pkinit_plg_opts *opts) 97 { 98 free(opts); 99 return; 100 } 101 102 void 103 free_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in) 104 { 105 if (*in == NULL) return; 106 free((*in)->signedAuthPack.data); 107 if ((*in)->trustedCertifiers != NULL) 108 free_krb5_external_principal_identifier(&(*in)->trustedCertifiers); 109 free((*in)->kdcPkId.data); 110 free(*in); 111 } 112 113 void 114 free_krb5_reply_key_pack(krb5_reply_key_pack **in) 115 { 116 if (*in == NULL) return; 117 free((*in)->replyKey.contents); 118 free((*in)->asChecksum.contents); 119 free(*in); 120 } 121 122 void 123 free_krb5_auth_pack(krb5_auth_pack **in) 124 { 125 if ((*in) == NULL) return; 126 krb5_free_data_contents(NULL, &(*in)->clientPublicValue); 127 free((*in)->pkAuthenticator.paChecksum.contents); 128 krb5_free_data(NULL, (*in)->pkAuthenticator.freshnessToken); 129 if ((*in)->supportedCMSTypes != NULL) 130 free_krb5_algorithm_identifiers(&((*in)->supportedCMSTypes)); 131 if ((*in)->supportedKDFs) { 132 krb5_data **supportedKDFs = (*in)->supportedKDFs; 133 unsigned i; 134 for (i = 0; supportedKDFs[i]; i++) 135 krb5_free_data(NULL, supportedKDFs[i]); 136 free(supportedKDFs); 137 } 138 free(*in); 139 } 140 141 void 142 free_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in) 143 { 144 if (*in == NULL) return; 145 switch ((*in)->choice) { 146 case choice_pa_pk_as_rep_dhInfo: 147 krb5_free_data(NULL, (*in)->u.dh_Info.kdfID); 148 free((*in)->u.dh_Info.dhSignedData.data); 149 break; 150 case choice_pa_pk_as_rep_encKeyPack: 151 free((*in)->u.encKeyPack.data); 152 break; 153 default: 154 break; 155 } 156 free(*in); 157 } 158 159 void 160 free_krb5_external_principal_identifier(krb5_external_principal_identifier ***in) 161 { 162 int i = 0; 163 if (*in == NULL) return; 164 while ((*in)[i] != NULL) { 165 free((*in)[i]->subjectName.data); 166 free((*in)[i]->issuerAndSerialNumber.data); 167 free((*in)[i]->subjectKeyIdentifier.data); 168 free((*in)[i]); 169 i++; 170 } 171 free(*in); 172 } 173 174 void 175 free_krb5_algorithm_identifier(krb5_algorithm_identifier *in) 176 { 177 if (in == NULL) 178 return; 179 free(in->algorithm.data); 180 free(in->parameters.data); 181 free(in); 182 } 183 184 void 185 free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in) 186 { 187 int i; 188 if (in == NULL || *in == NULL) 189 return; 190 for (i = 0; (*in)[i] != NULL; i++) { 191 free_krb5_algorithm_identifier((*in)[i]); 192 } 193 free(*in); 194 } 195 196 void 197 free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in) 198 { 199 if (*in == NULL) return; 200 free((*in)->subjectPublicKey.data); 201 free(*in); 202 } 203 204 void 205 init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in) 206 { 207 (*in) = malloc(sizeof(krb5_pa_pk_as_req)); 208 if ((*in) == NULL) return; 209 (*in)->signedAuthPack.data = NULL; 210 (*in)->signedAuthPack.length = 0; 211 (*in)->trustedCertifiers = NULL; 212 (*in)->kdcPkId.data = NULL; 213 (*in)->kdcPkId.length = 0; 214 } 215 216 void 217 init_krb5_reply_key_pack(krb5_reply_key_pack **in) 218 { 219 (*in) = malloc(sizeof(krb5_reply_key_pack)); 220 if ((*in) == NULL) return; 221 (*in)->replyKey.contents = NULL; 222 (*in)->replyKey.length = 0; 223 (*in)->asChecksum.contents = NULL; 224 (*in)->asChecksum.length = 0; 225 } 226 227 void 228 init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in) 229 { 230 (*in) = malloc(sizeof(krb5_pa_pk_as_rep)); 231 if ((*in) == NULL) return; 232 (*in)->u.dh_Info.serverDHNonce.length = 0; 233 (*in)->u.dh_Info.serverDHNonce.data = NULL; 234 (*in)->u.dh_Info.dhSignedData.length = 0; 235 (*in)->u.dh_Info.dhSignedData.data = NULL; 236 (*in)->u.encKeyPack.length = 0; 237 (*in)->u.encKeyPack.data = NULL; 238 (*in)->u.dh_Info.kdfID = NULL; 239 } 240 241 krb5_error_code 242 pkinit_copy_krb5_data(krb5_data *dst, const krb5_data *src) 243 { 244 if (dst == NULL || src == NULL) 245 return EINVAL; 246 if (src->data == NULL) { 247 dst->data = NULL; 248 dst->length = 0; 249 return 0; 250 } 251 dst->data = malloc(src->length); 252 if (dst->data == NULL) 253 return ENOMEM; 254 memcpy(dst->data, src->data, src->length); 255 dst->length = src->length; 256 return 0; 257 } 258 259 /* debugging functions */ 260 void 261 print_buffer(const unsigned char *buf, unsigned int len) 262 { 263 unsigned i = 0; 264 if (len <= 0) 265 return; 266 267 for (i = 0; i < len; i++) 268 pkiDebug("%02x ", buf[i]); 269 pkiDebug("\n"); 270 } 271 272 void 273 print_buffer_bin(unsigned char *buf, unsigned int len, char *filename) 274 { 275 FILE *f = NULL; 276 unsigned int i = 0; 277 278 if (len <= 0 || filename == NULL) 279 return; 280 281 if ((f = fopen(filename, "w")) == NULL) 282 return; 283 284 set_cloexec_file(f); 285 286 for (i = 0; i < len; i++) 287 fputc(buf[i], f); 288 289 fclose(f); 290 } 291