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 "k5-int.h" 33 #include "pkinit.h" 34 35 #define FAKECERT 36 37 krb5_error_code 38 pkinit_init_req_opts(pkinit_req_opts **reqopts) 39 { 40 krb5_error_code retval = ENOMEM; 41 pkinit_req_opts *opts = NULL; 42 43 *reqopts = NULL; 44 opts = calloc(1, sizeof(*opts)); 45 if (opts == NULL) 46 return retval; 47 48 opts->require_eku = 1; 49 opts->accept_secondary_eku = 0; 50 opts->allow_upn = 0; 51 opts->require_crl_checking = 0; 52 opts->dh_size = PKINIT_DEFAULT_DH_MIN_BITS; 53 54 *reqopts = opts; 55 56 return 0; 57 } 58 59 void 60 pkinit_fini_req_opts(pkinit_req_opts *opts) 61 { 62 free(opts); 63 return; 64 } 65 66 krb5_error_code 67 pkinit_init_plg_opts(pkinit_plg_opts **plgopts) 68 { 69 krb5_error_code retval = ENOMEM; 70 pkinit_plg_opts *opts = NULL; 71 72 *plgopts = NULL; 73 opts = calloc(1, sizeof(pkinit_plg_opts)); 74 if (opts == NULL) 75 return retval; 76 77 opts->require_eku = 1; 78 opts->accept_secondary_eku = 0; 79 opts->allow_upn = 0; 80 opts->require_crl_checking = 0; 81 opts->require_freshness = 0; 82 opts->disable_freshness = 0; 83 84 opts->dh_min_bits = PKINIT_DEFAULT_DH_MIN_BITS; 85 86 *plgopts = opts; 87 88 return 0; 89 } 90 91 void 92 pkinit_fini_plg_opts(pkinit_plg_opts *opts) 93 { 94 free(opts); 95 return; 96 } 97 98 void 99 free_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in) 100 { 101 if (*in == NULL) return; 102 free((*in)->signedAuthPack.data); 103 if ((*in)->trustedCertifiers != NULL) 104 free_krb5_external_principal_identifier(&(*in)->trustedCertifiers); 105 free((*in)->kdcPkId.data); 106 free(*in); 107 } 108 109 void 110 free_krb5_reply_key_pack(krb5_reply_key_pack **in) 111 { 112 if (*in == NULL) return; 113 free((*in)->replyKey.contents); 114 free((*in)->asChecksum.contents); 115 free(*in); 116 } 117 118 void 119 free_krb5_auth_pack(krb5_auth_pack **in) 120 { 121 if ((*in) == NULL) return; 122 krb5_free_data_contents(NULL, &(*in)->clientPublicValue); 123 free((*in)->pkAuthenticator.paChecksum.data); 124 krb5_free_data(NULL, (*in)->pkAuthenticator.freshnessToken); 125 free_pachecksum2(NULL, &(*in)->pkAuthenticator.paChecksum2); 126 if ((*in)->supportedCMSTypes != NULL) 127 free_krb5_algorithm_identifiers(&((*in)->supportedCMSTypes)); 128 if ((*in)->supportedKDFs) { 129 krb5_data **supportedKDFs = (*in)->supportedKDFs; 130 unsigned i; 131 for (i = 0; supportedKDFs[i]; i++) 132 krb5_free_data(NULL, supportedKDFs[i]); 133 free(supportedKDFs); 134 } 135 free(*in); 136 } 137 138 void 139 free_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in) 140 { 141 if (*in == NULL) return; 142 switch ((*in)->choice) { 143 case choice_pa_pk_as_rep_dhInfo: 144 krb5_free_data(NULL, (*in)->u.dh_Info.kdfID); 145 free((*in)->u.dh_Info.dhSignedData.data); 146 break; 147 case choice_pa_pk_as_rep_encKeyPack: 148 free((*in)->u.encKeyPack.data); 149 break; 150 default: 151 break; 152 } 153 free(*in); 154 } 155 156 void 157 free_krb5_external_principal_identifier(krb5_external_principal_identifier ***in) 158 { 159 int i = 0; 160 if (*in == NULL) return; 161 while ((*in)[i] != NULL) { 162 free((*in)[i]->subjectName.data); 163 free((*in)[i]->issuerAndSerialNumber.data); 164 free((*in)[i]->subjectKeyIdentifier.data); 165 free((*in)[i]); 166 i++; 167 } 168 free(*in); 169 } 170 171 void 172 free_krb5_algorithm_identifier(krb5_algorithm_identifier *in) 173 { 174 if (in == NULL) 175 return; 176 free(in->algorithm.data); 177 free(in->parameters.data); 178 free(in); 179 } 180 181 void 182 free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in) 183 { 184 int i; 185 if (in == NULL || *in == NULL) 186 return; 187 for (i = 0; (*in)[i] != NULL; i++) { 188 free_krb5_algorithm_identifier((*in)[i]); 189 } 190 free(*in); 191 } 192 193 void 194 free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in) 195 { 196 if (*in == NULL) return; 197 free((*in)->subjectPublicKey.data); 198 free(*in); 199 } 200 201 void 202 free_pachecksum2(krb5_context context, krb5_pachecksum2 **in) 203 { 204 if (*in == NULL) 205 return; 206 krb5_free_data_contents(context, &(*in)->checksum); 207 krb5_free_data_contents(context, &(*in)->algorithmIdentifier.algorithm); 208 krb5_free_data_contents(context, &(*in)->algorithmIdentifier.parameters); 209 free(*in); 210 *in = NULL; 211 } 212 213 void 214 init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in) 215 { 216 (*in) = malloc(sizeof(krb5_pa_pk_as_req)); 217 if ((*in) == NULL) return; 218 (*in)->signedAuthPack.data = NULL; 219 (*in)->signedAuthPack.length = 0; 220 (*in)->trustedCertifiers = NULL; 221 (*in)->kdcPkId.data = NULL; 222 (*in)->kdcPkId.length = 0; 223 } 224 225 void 226 init_krb5_reply_key_pack(krb5_reply_key_pack **in) 227 { 228 (*in) = malloc(sizeof(krb5_reply_key_pack)); 229 if ((*in) == NULL) return; 230 (*in)->replyKey.contents = NULL; 231 (*in)->replyKey.length = 0; 232 (*in)->asChecksum.contents = NULL; 233 (*in)->asChecksum.length = 0; 234 } 235 236 void 237 init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in) 238 { 239 (*in) = malloc(sizeof(krb5_pa_pk_as_rep)); 240 if ((*in) == NULL) return; 241 (*in)->u.dh_Info.serverDHNonce.length = 0; 242 (*in)->u.dh_Info.serverDHNonce.data = NULL; 243 (*in)->u.dh_Info.dhSignedData.length = 0; 244 (*in)->u.dh_Info.dhSignedData.data = NULL; 245 (*in)->u.encKeyPack.length = 0; 246 (*in)->u.encKeyPack.data = NULL; 247 (*in)->u.dh_Info.kdfID = NULL; 248 } 249 250 krb5_error_code 251 pkinit_copy_krb5_data(krb5_data *dst, const krb5_data *src) 252 { 253 if (dst == NULL || src == NULL) 254 return EINVAL; 255 if (src->data == NULL) { 256 dst->data = NULL; 257 dst->length = 0; 258 return 0; 259 } 260 dst->data = malloc(src->length); 261 if (dst->data == NULL) 262 return ENOMEM; 263 memcpy(dst->data, src->data, src->length); 264 dst->length = src->length; 265 return 0; 266 } 267 268 /* debugging functions */ 269 void 270 print_buffer(const unsigned char *buf, unsigned int len) 271 { 272 unsigned i = 0; 273 if (len <= 0) 274 return; 275 276 for (i = 0; i < len; i++) 277 pkiDebug("%02x ", buf[i]); 278 pkiDebug("\n"); 279 } 280 281 void 282 print_buffer_bin(unsigned char *buf, unsigned int len, char *filename) 283 { 284 FILE *f = NULL; 285 unsigned int i = 0; 286 287 if (len <= 0 || filename == NULL) 288 return; 289 290 if ((f = fopen(filename, "w")) == NULL) 291 return; 292 293 set_cloexec_file(f); 294 295 for (i = 0; i < len; i++) 296 fputc(buf[i], f); 297 298 fclose(f); 299 } 300