1 /* 2 * COPYRIGHT (C) 2006,2007 3 * THE REGENTS OF THE UNIVERSITY OF MICHIGAN 4 * ALL RIGHTS RESERVED 5 * 6 * Permission is granted to use, copy, create derivative works 7 * and redistribute this software and such derivative works 8 * for any purpose, so long as the name of The University of 9 * Michigan is not used in any advertising or publicity 10 * pertaining to the use of distribution of this software 11 * without specific, written prior authorization. If the 12 * above copyright notice or any other identification of the 13 * University of Michigan is included in any copy of any 14 * portion of this software, then the disclaimer below must 15 * also be included. 16 * 17 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION 18 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY 19 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF 20 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING 21 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF 22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 23 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE 24 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR 25 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING 26 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN 27 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGES. 29 */ 30 31 /* 32 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 33 * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved. 34 * Copyright 2017 RackTop Systems. 35 */ 36 37 #include <errno.h> 38 #include <string.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <dlfcn.h> 42 #include <unistd.h> 43 #include <dirent.h> 44 45 46 /* Solaris Kerberos */ 47 #include <libintl.h> 48 #include <assert.h> 49 #include <security/pam_appl.h> 50 #include <ctype.h> 51 #include "k5-int.h" 52 #include <ctype.h> 53 54 /* 55 * Q: What is this SILLYDECRYPT stuff about? 56 * A: When using the ActivCard Linux pkcs11 library (v2.0.1), 57 * the decrypt function fails. By inserting an extra 58 * function call, which serves nothing but to change the 59 * stack, we were able to work around the issue. If the 60 * ActivCard library is fixed in the future, this 61 * definition and related code can be removed. 62 */ 63 #define SILLYDECRYPT 64 65 #include "pkinit_crypto_openssl.h" 66 67 /* 68 * Solaris Kerberos: 69 * Changed to a switch statement so gettext() can be used 70 * for internationization. 71 * Use defined constants rather than raw numbers for error codes. 72 */ 73 static char * 74 pkcs11_error_table(short code) { 75 switch (code) { 76 case CKR_OK: 77 return (gettext("ok")); 78 case CKR_CANCEL: 79 return (gettext("cancel")); 80 case CKR_HOST_MEMORY: 81 return (gettext("host memory")); 82 case CKR_SLOT_ID_INVALID: 83 return (gettext("slot id invalid")); 84 case CKR_GENERAL_ERROR: 85 return (gettext("general error")); 86 case CKR_FUNCTION_FAILED: 87 return (gettext("function failed")); 88 case CKR_ARGUMENTS_BAD: 89 return (gettext("arguments bad")); 90 case CKR_NO_EVENT: 91 return (gettext("no event")); 92 case CKR_NEED_TO_CREATE_THREADS: 93 return (gettext("need to create threads")); 94 case CKR_CANT_LOCK: 95 return (gettext("cant lock")); 96 case CKR_ATTRIBUTE_READ_ONLY: 97 return (gettext("attribute read only")); 98 case CKR_ATTRIBUTE_SENSITIVE: 99 return (gettext("attribute sensitive")); 100 case CKR_ATTRIBUTE_TYPE_INVALID: 101 return (gettext("attribute type invalid")); 102 case CKR_ATTRIBUTE_VALUE_INVALID: 103 return (gettext("attribute value invalid")); 104 case CKR_DATA_INVALID: 105 return (gettext("data invalid")); 106 case CKR_DATA_LEN_RANGE: 107 return (gettext("data len range")); 108 case CKR_DEVICE_ERROR: 109 return (gettext("device error")); 110 case CKR_DEVICE_MEMORY: 111 return (gettext("device memory")); 112 case CKR_DEVICE_REMOVED: 113 return (gettext("device removed")); 114 case CKR_ENCRYPTED_DATA_INVALID: 115 return (gettext("encrypted data invalid")); 116 case CKR_ENCRYPTED_DATA_LEN_RANGE: 117 return (gettext("encrypted data len range")); 118 case CKR_FUNCTION_CANCELED: 119 return (gettext("function canceled")); 120 case CKR_FUNCTION_NOT_PARALLEL: 121 return (gettext("function not parallel")); 122 case CKR_FUNCTION_NOT_SUPPORTED: 123 return (gettext("function not supported")); 124 case CKR_KEY_HANDLE_INVALID: 125 return (gettext("key handle invalid")); 126 case CKR_KEY_SIZE_RANGE: 127 return (gettext("key size range")); 128 case CKR_KEY_TYPE_INCONSISTENT: 129 return (gettext("key type inconsistent")); 130 case CKR_KEY_NOT_NEEDED: 131 return (gettext("key not needed")); 132 case CKR_KEY_CHANGED: 133 return (gettext("key changed")); 134 case CKR_KEY_NEEDED: 135 return (gettext("key needed")); 136 case CKR_KEY_INDIGESTIBLE: 137 return (gettext("key indigestible")); 138 case CKR_KEY_FUNCTION_NOT_PERMITTED: 139 return (gettext("key function not permitted")); 140 case CKR_KEY_NOT_WRAPPABLE: 141 return (gettext("key not wrappable")); 142 case CKR_KEY_UNEXTRACTABLE: 143 return (gettext("key unextractable")); 144 case CKR_MECHANISM_INVALID: 145 return (gettext("mechanism invalid")); 146 case CKR_MECHANISM_PARAM_INVALID: 147 return (gettext("mechanism param invalid")); 148 case CKR_OBJECT_HANDLE_INVALID: 149 return (gettext("object handle invalid")); 150 case CKR_OPERATION_ACTIVE: 151 return (gettext("operation active")); 152 case CKR_OPERATION_NOT_INITIALIZED: 153 return (gettext("operation not initialized")); 154 case CKR_PIN_INCORRECT: 155 return (gettext("pin incorrect")); 156 case CKR_PIN_INVALID: 157 return (gettext("pin invalid")); 158 case CKR_PIN_LEN_RANGE: 159 return (gettext("pin len range")); 160 case CKR_PIN_EXPIRED: 161 return (gettext("pin expired")); 162 case CKR_PIN_LOCKED: 163 return (gettext("pin locked")); 164 case CKR_SESSION_CLOSED: 165 return (gettext("session closed")); 166 case CKR_SESSION_COUNT: 167 return (gettext("session count")); 168 case CKR_SESSION_HANDLE_INVALID: 169 return (gettext("session handle invalid")); 170 case CKR_SESSION_PARALLEL_NOT_SUPPORTED: 171 return (gettext("session parallel not supported")); 172 case CKR_SESSION_READ_ONLY: 173 return (gettext("session read only")); 174 case CKR_SESSION_EXISTS: 175 return (gettext("session exists")); 176 case CKR_SESSION_READ_ONLY_EXISTS: 177 return (gettext("session read only exists")); 178 case CKR_SESSION_READ_WRITE_SO_EXISTS: 179 return (gettext("session read write so exists")); 180 case CKR_SIGNATURE_INVALID: 181 return (gettext("signature invalid")); 182 case CKR_SIGNATURE_LEN_RANGE: 183 return (gettext("signature len range")); 184 case CKR_TEMPLATE_INCOMPLETE: 185 return (gettext("template incomplete")); 186 case CKR_TEMPLATE_INCONSISTENT: 187 return (gettext("template inconsistent")); 188 case CKR_TOKEN_NOT_PRESENT: 189 return (gettext("token not present")); 190 case CKR_TOKEN_NOT_RECOGNIZED: 191 return (gettext("token not recognized")); 192 case CKR_TOKEN_WRITE_PROTECTED: 193 return (gettext("token write protected")); 194 case CKR_UNWRAPPING_KEY_HANDLE_INVALID: 195 return (gettext("unwrapping key handle invalid")); 196 case CKR_UNWRAPPING_KEY_SIZE_RANGE: 197 return (gettext("unwrapping key size range")); 198 case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT: 199 return (gettext("unwrapping key type inconsistent")); 200 case CKR_USER_ALREADY_LOGGED_IN: 201 return (gettext("user already logged in")); 202 case CKR_USER_NOT_LOGGED_IN: 203 return (gettext("user not logged in")); 204 case CKR_USER_PIN_NOT_INITIALIZED: 205 return (gettext("user pin not initialized")); 206 case CKR_USER_TYPE_INVALID: 207 return (gettext("user type invalid")); 208 case CKR_USER_ANOTHER_ALREADY_LOGGED_IN: 209 return (gettext("user another already logged in")); 210 case CKR_USER_TOO_MANY_TYPES: 211 return (gettext("user too many types")); 212 case CKR_WRAPPED_KEY_INVALID: 213 return (gettext("wrapped key invalid")); 214 case CKR_WRAPPED_KEY_LEN_RANGE: 215 return (gettext("wrapped key len range")); 216 case CKR_WRAPPING_KEY_HANDLE_INVALID: 217 return (gettext("wrapping key handle invalid")); 218 case CKR_WRAPPING_KEY_SIZE_RANGE: 219 return (gettext("wrapping key size range")); 220 case CKR_WRAPPING_KEY_TYPE_INCONSISTENT: 221 return (gettext("wrapping key type inconsistent")); 222 case CKR_RANDOM_SEED_NOT_SUPPORTED: 223 return (gettext("random seed not supported")); 224 case CKR_RANDOM_NO_RNG: 225 return (gettext("random no rng")); 226 case CKR_DOMAIN_PARAMS_INVALID: 227 return (gettext("domain params invalid")); 228 case CKR_BUFFER_TOO_SMALL: 229 return (gettext("buffer too small")); 230 case CKR_SAVED_STATE_INVALID: 231 return (gettext("saved state invalid")); 232 case CKR_INFORMATION_SENSITIVE: 233 return (gettext("information sensitive")); 234 case CKR_STATE_UNSAVEABLE: 235 return (gettext("state unsaveable")); 236 case CKR_CRYPTOKI_NOT_INITIALIZED: 237 return (gettext("cryptoki not initialized")); 238 case CKR_CRYPTOKI_ALREADY_INITIALIZED: 239 return (gettext("cryptoki already initialized")); 240 case CKR_MUTEX_BAD: 241 return (gettext("mutex bad")); 242 case CKR_MUTEX_NOT_LOCKED: 243 return (gettext("mutex not locked")); 244 case CKR_FUNCTION_REJECTED: 245 return (gettext("function rejected")); 246 default: 247 return (gettext("unknown error")); 248 } 249 } 250 251 /* DH parameters */ 252 unsigned char pkinit_1024_dhprime[128] = { 253 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 254 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 255 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 256 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 257 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 258 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 259 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 260 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 261 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 262 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 263 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 264 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 265 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 266 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 267 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, 268 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 269 }; 270 271 unsigned char pkinit_2048_dhprime[2048/8] = { 272 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 273 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 274 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 275 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 276 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 277 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 278 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 279 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 280 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 281 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 282 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 283 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 284 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 285 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 286 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 287 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 288 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 289 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 290 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 291 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 292 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 293 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 294 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 295 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 296 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 297 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 298 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 299 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 300 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 301 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 302 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 303 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 304 }; 305 306 unsigned char pkinit_4096_dhprime[4096/8] = { 307 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 308 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 309 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 310 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 311 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 312 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 313 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 314 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 315 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 316 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 317 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 318 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 319 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 320 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 321 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 322 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 323 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 324 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 325 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 326 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 327 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 328 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 329 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 330 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 331 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 332 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 333 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 334 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 335 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 336 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 337 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 338 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 339 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 340 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 341 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 342 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 343 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 344 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 345 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 346 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 347 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 348 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 349 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 350 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 351 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 352 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 353 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 354 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 355 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 356 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 357 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 358 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 359 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 360 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, 361 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 362 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 363 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 364 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 365 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 366 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, 367 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 368 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 369 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, 370 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 371 }; 372 373 krb5_error_code 374 pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx) { 375 376 krb5_error_code retval = ENOMEM; 377 pkinit_plg_crypto_context ctx = NULL; 378 379 /* initialize openssl routines */ 380 /* Solaris Kerberos */ 381 retval = openssl_init(); 382 if (retval != 0) 383 goto out; 384 385 ctx = (pkinit_plg_crypto_context)malloc(sizeof(*ctx)); 386 if (ctx == NULL) 387 goto out; 388 (void) memset(ctx, 0, sizeof(*ctx)); 389 390 pkiDebug("%s: initializing openssl crypto context at %p\n", 391 __FUNCTION__, ctx); 392 retval = pkinit_init_pkinit_oids(ctx); 393 if (retval) 394 goto out; 395 396 retval = pkinit_init_dh_params(ctx); 397 if (retval) 398 goto out; 399 400 *cryptoctx = ctx; 401 402 out: 403 if (retval && ctx != NULL) 404 pkinit_fini_plg_crypto(ctx); 405 406 return retval; 407 } 408 409 void 410 pkinit_fini_plg_crypto(pkinit_plg_crypto_context cryptoctx) 411 { 412 pkiDebug("%s: freeing context at %p\n", __FUNCTION__, cryptoctx); 413 414 if (cryptoctx == NULL) 415 return; 416 pkinit_fini_pkinit_oids(cryptoctx); 417 pkinit_fini_dh_params(cryptoctx); 418 free(cryptoctx); 419 } 420 421 krb5_error_code 422 pkinit_init_identity_crypto(pkinit_identity_crypto_context *idctx) 423 { 424 krb5_error_code retval = ENOMEM; 425 pkinit_identity_crypto_context ctx = NULL; 426 427 ctx = (pkinit_identity_crypto_context)malloc(sizeof(*ctx)); 428 if (ctx == NULL) 429 goto out; 430 (void) memset(ctx, 0, sizeof(*ctx)); 431 432 retval = pkinit_init_certs(ctx); 433 if (retval) 434 goto out; 435 436 retval = pkinit_init_pkcs11(ctx); 437 if (retval) 438 goto out; 439 440 pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx); 441 *idctx = ctx; 442 443 out: 444 if (retval) { 445 if (ctx) 446 pkinit_fini_identity_crypto(ctx); 447 } 448 449 return retval; 450 } 451 452 void 453 pkinit_fini_identity_crypto(pkinit_identity_crypto_context idctx) 454 { 455 if (idctx == NULL) 456 return; 457 458 pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__, idctx); 459 pkinit_fini_certs(idctx); 460 pkinit_fini_pkcs11(idctx); 461 free(idctx); 462 } 463 464 krb5_error_code 465 pkinit_init_req_crypto(pkinit_req_crypto_context *cryptoctx) 466 { 467 468 pkinit_req_crypto_context ctx = NULL; 469 470 /* Solaris Kerberos */ 471 if (cryptoctx == NULL) 472 return EINVAL; 473 474 ctx = (pkinit_req_crypto_context)malloc(sizeof(*ctx)); 475 if (ctx == NULL) 476 return ENOMEM; 477 (void) memset(ctx, 0, sizeof(*ctx)); 478 479 ctx->dh = NULL; 480 ctx->received_cert = NULL; 481 482 *cryptoctx = ctx; 483 484 pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx); 485 486 return 0; 487 } 488 489 void 490 pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx) 491 { 492 if (req_cryptoctx == NULL) 493 return; 494 495 pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__, req_cryptoctx); 496 if (req_cryptoctx->dh != NULL) 497 DH_free(req_cryptoctx->dh); 498 if (req_cryptoctx->received_cert != NULL) 499 X509_free(req_cryptoctx->received_cert); 500 501 free(req_cryptoctx); 502 } 503 504 static krb5_error_code 505 pkinit_init_pkinit_oids(pkinit_plg_crypto_context ctx) 506 { 507 ctx->id_pkinit_san = OBJ_txt2obj("1.3.6.1.5.2.2", 1); 508 if (ctx->id_pkinit_san == NULL) 509 return ENOMEM; 510 511 ctx->id_pkinit_authData = OBJ_txt2obj("1.3.6.1.5.2.3.1", 1); 512 if (ctx->id_pkinit_authData == NULL) 513 return ENOMEM; 514 515 ctx->id_pkinit_DHKeyData = OBJ_txt2obj("1.3.6.1.5.2.3.2", 1); 516 if (ctx->id_pkinit_DHKeyData == NULL) 517 return ENOMEM; 518 519 ctx->id_pkinit_rkeyData = OBJ_txt2obj("1.3.6.1.5.2.3.3", 1); 520 if (ctx->id_pkinit_rkeyData == NULL) 521 return ENOMEM; 522 523 ctx->id_pkinit_KPClientAuth = OBJ_txt2obj("1.3.6.1.5.2.3.4", 1); 524 if (ctx->id_pkinit_KPClientAuth == NULL) 525 return ENOMEM; 526 527 ctx->id_pkinit_KPKdc = OBJ_txt2obj("1.3.6.1.5.2.3.5", 1); 528 if (ctx->id_pkinit_KPKdc == NULL) 529 return ENOMEM; 530 531 ctx->id_ms_kp_sc_logon = OBJ_txt2obj("1.3.6.1.4.1.311.20.2.2", 1); 532 if (ctx->id_ms_kp_sc_logon == NULL) 533 return ENOMEM; 534 535 ctx->id_ms_san_upn = OBJ_txt2obj("1.3.6.1.4.1.311.20.2.3", 1); 536 if (ctx->id_ms_san_upn == NULL) 537 return ENOMEM; 538 539 ctx->id_kp_serverAuth = OBJ_txt2obj("1.3.6.1.5.5.7.3.1", 1); 540 if (ctx->id_kp_serverAuth == NULL) 541 return ENOMEM; 542 543 return 0; 544 } 545 546 static krb5_error_code 547 get_cert(char *filename, X509 **retcert) 548 { 549 X509 *cert = NULL; 550 BIO *tmp = NULL; 551 int code; 552 krb5_error_code retval; 553 554 if (filename == NULL || retcert == NULL) 555 return EINVAL; 556 557 *retcert = NULL; 558 559 tmp = BIO_new(BIO_s_file()); 560 if (tmp == NULL) 561 return ENOMEM; 562 563 code = BIO_read_filename(tmp, filename); 564 if (code == 0) { 565 retval = errno; 566 goto cleanup; 567 } 568 569 cert = (X509 *) PEM_read_bio_X509(tmp, NULL, NULL, NULL); 570 if (cert == NULL) { 571 retval = EIO; 572 pkiDebug("failed to read certificate from %s\n", filename); 573 goto cleanup; 574 } 575 *retcert = cert; 576 retval = 0; 577 cleanup: 578 if (tmp != NULL) 579 BIO_free(tmp); 580 return retval; 581 } 582 583 static krb5_error_code 584 get_key(char *filename, EVP_PKEY **retkey) 585 { 586 EVP_PKEY *pkey = NULL; 587 BIO *tmp = NULL; 588 int code; 589 krb5_error_code retval; 590 591 if (filename == NULL || retkey == NULL) 592 return EINVAL; 593 594 tmp = BIO_new(BIO_s_file()); 595 if (tmp == NULL) 596 return ENOMEM; 597 598 code = BIO_read_filename(tmp, filename); 599 if (code == 0) { 600 retval = errno; 601 goto cleanup; 602 } 603 pkey = (EVP_PKEY *) PEM_read_bio_PrivateKey(tmp, NULL, NULL, NULL); 604 if (pkey == NULL) { 605 retval = EIO; 606 pkiDebug("failed to read private key from %s\n", filename); 607 goto cleanup; 608 } 609 *retkey = pkey; 610 retval = 0; 611 cleanup: 612 if (tmp != NULL) 613 BIO_free(tmp); 614 return retval; 615 } 616 617 static void 618 pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx) 619 { 620 if (ctx == NULL) 621 return; 622 ASN1_OBJECT_free(ctx->id_pkinit_san); 623 ASN1_OBJECT_free(ctx->id_pkinit_authData); 624 ASN1_OBJECT_free(ctx->id_pkinit_DHKeyData); 625 ASN1_OBJECT_free(ctx->id_pkinit_rkeyData); 626 ASN1_OBJECT_free(ctx->id_pkinit_KPClientAuth); 627 ASN1_OBJECT_free(ctx->id_pkinit_KPKdc); 628 ASN1_OBJECT_free(ctx->id_ms_kp_sc_logon); 629 ASN1_OBJECT_free(ctx->id_ms_san_upn); 630 ASN1_OBJECT_free(ctx->id_kp_serverAuth); 631 } 632 633 static krb5_error_code 634 pkinit_init_dh_params(pkinit_plg_crypto_context plgctx) 635 { 636 krb5_error_code retval = ENOMEM; 637 638 plgctx->dh_1024 = DH_new(); 639 if (plgctx->dh_1024 == NULL) 640 goto cleanup; 641 plgctx->dh_1024->p = BN_bin2bn(pkinit_1024_dhprime, 642 sizeof(pkinit_1024_dhprime), NULL); 643 if ((plgctx->dh_1024->g = BN_new()) == NULL || 644 (plgctx->dh_1024->q = BN_new()) == NULL) 645 goto cleanup; 646 BN_set_word(plgctx->dh_1024->g, DH_GENERATOR_2); 647 BN_rshift1(plgctx->dh_1024->q, plgctx->dh_1024->p); 648 649 plgctx->dh_2048 = DH_new(); 650 if (plgctx->dh_2048 == NULL) 651 goto cleanup; 652 plgctx->dh_2048->p = BN_bin2bn(pkinit_2048_dhprime, 653 sizeof(pkinit_2048_dhprime), NULL); 654 if ((plgctx->dh_2048->g = BN_new()) == NULL || 655 (plgctx->dh_2048->q = BN_new()) == NULL) 656 goto cleanup; 657 BN_set_word(plgctx->dh_2048->g, DH_GENERATOR_2); 658 BN_rshift1(plgctx->dh_2048->q, plgctx->dh_2048->p); 659 660 plgctx->dh_4096 = DH_new(); 661 if (plgctx->dh_4096 == NULL) 662 goto cleanup; 663 plgctx->dh_4096->p = BN_bin2bn(pkinit_4096_dhprime, 664 sizeof(pkinit_4096_dhprime), NULL); 665 if ((plgctx->dh_4096->g = BN_new()) == NULL || 666 (plgctx->dh_4096->q = BN_new()) == NULL) 667 goto cleanup; 668 BN_set_word(plgctx->dh_4096->g, DH_GENERATOR_2); 669 BN_rshift1(plgctx->dh_4096->q, plgctx->dh_4096->p); 670 671 retval = 0; 672 673 cleanup: 674 if (retval) 675 pkinit_fini_dh_params(plgctx); 676 677 return retval; 678 } 679 680 static void 681 pkinit_fini_dh_params(pkinit_plg_crypto_context plgctx) 682 { 683 if (plgctx->dh_1024 != NULL) 684 DH_free(plgctx->dh_1024); 685 if (plgctx->dh_2048 != NULL) 686 DH_free(plgctx->dh_2048); 687 if (plgctx->dh_4096 != NULL) 688 DH_free(plgctx->dh_4096); 689 690 plgctx->dh_1024 = plgctx->dh_2048 = plgctx->dh_4096 = NULL; 691 } 692 693 static krb5_error_code 694 pkinit_init_certs(pkinit_identity_crypto_context ctx) 695 { 696 /* Solaris Kerberos */ 697 int i; 698 699 for (i = 0; i < MAX_CREDS_ALLOWED; i++) 700 ctx->creds[i] = NULL; 701 ctx->my_certs = NULL; 702 ctx->cert_index = 0; 703 ctx->my_key = NULL; 704 ctx->trustedCAs = NULL; 705 ctx->intermediateCAs = NULL; 706 ctx->revoked = NULL; 707 708 return 0; 709 } 710 711 static void 712 pkinit_fini_certs(pkinit_identity_crypto_context ctx) 713 { 714 if (ctx == NULL) 715 return; 716 717 if (ctx->my_certs != NULL) 718 sk_X509_pop_free(ctx->my_certs, X509_free); 719 720 if (ctx->my_key != NULL) 721 EVP_PKEY_free(ctx->my_key); 722 723 if (ctx->trustedCAs != NULL) 724 sk_X509_pop_free(ctx->trustedCAs, X509_free); 725 726 if (ctx->intermediateCAs != NULL) 727 sk_X509_pop_free(ctx->intermediateCAs, X509_free); 728 729 if (ctx->revoked != NULL) 730 sk_X509_CRL_pop_free(ctx->revoked, X509_CRL_free); 731 } 732 733 static krb5_error_code 734 pkinit_init_pkcs11(pkinit_identity_crypto_context ctx) 735 { 736 /* Solaris Kerberos */ 737 738 #ifndef WITHOUT_PKCS11 739 ctx->p11_module_name = strdup(PKCS11_MODNAME); 740 if (ctx->p11_module_name == NULL) 741 return ENOMEM; 742 ctx->p11_module = NULL; 743 ctx->slotid = PK_NOSLOT; 744 ctx->token_label = NULL; 745 ctx->cert_label = NULL; 746 ctx->PIN = NULL; 747 ctx->session = CK_INVALID_HANDLE; 748 ctx->p11 = NULL; 749 ctx->p11flags = 0; /* Solaris Kerberos */ 750 #endif 751 ctx->pkcs11_method = 0; 752 (void) memset(ctx->creds, 0, sizeof(ctx->creds)); 753 754 return 0; 755 } 756 757 static void 758 pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx) 759 { 760 #ifndef WITHOUT_PKCS11 761 if (ctx == NULL) 762 return; 763 764 if (ctx->p11 != NULL) { 765 if (ctx->session != CK_INVALID_HANDLE) { 766 ctx->p11->C_CloseSession(ctx->session); 767 ctx->session = CK_INVALID_HANDLE; 768 } 769 /* 770 * Solaris Kerberos: 771 * Only call C_Finalize if the process was not already using pkcs11. 772 */ 773 if (ctx->finalize_pkcs11 == TRUE) 774 ctx->p11->C_Finalize(NULL_PTR); 775 776 ctx->p11 = NULL; 777 } 778 if (ctx->p11_module != NULL) { 779 pkinit_C_UnloadModule(ctx->p11_module); 780 ctx->p11_module = NULL; 781 } 782 if (ctx->p11_module_name != NULL) 783 free(ctx->p11_module_name); 784 if (ctx->token_label != NULL) 785 free(ctx->token_label); 786 if (ctx->cert_id != NULL) 787 free(ctx->cert_id); 788 if (ctx->cert_label != NULL) 789 free(ctx->cert_label); 790 if (ctx->PIN != NULL) { 791 (void) memset(ctx->PIN, 0, strlen(ctx->PIN)); 792 free(ctx->PIN); 793 } 794 #endif 795 } 796 797 krb5_error_code 798 pkinit_identity_set_prompter(pkinit_identity_crypto_context id_cryptoctx, 799 krb5_prompter_fct prompter, 800 void *prompter_data) 801 { 802 id_cryptoctx->prompter = prompter; 803 id_cryptoctx->prompter_data = prompter_data; 804 805 return 0; 806 } 807 808 /* Create a CMS ContentInfo of type oid containing the octet string in data. */ 809 static krb5_error_code 810 create_contentinfo(krb5_context context, 811 ASN1_OBJECT *oid, 812 unsigned char *data, 813 size_t data_len, 814 PKCS7 **p7_out) 815 { 816 PKCS7 *p7 = NULL; 817 ASN1_OCTET_STRING *ostr = NULL; 818 819 *p7_out = NULL; 820 821 ostr = ASN1_OCTET_STRING_new(); 822 if (ostr == NULL) 823 goto oom; 824 if (!ASN1_OCTET_STRING_set(ostr, (unsigned char *)data, data_len)) 825 goto oom; 826 827 p7 = PKCS7_new(); 828 if (p7 == NULL) 829 goto oom; 830 p7->type = OBJ_dup(oid); 831 if (p7->type == NULL) 832 goto oom; 833 834 if (OBJ_obj2nid(oid) == NID_pkcs7_data) { 835 /* Draft 9 uses id-pkcs7-data for signed data. For this type OpenSSL 836 * expects an octet string in d.data. */ 837 p7->d.data = ostr; 838 } else { 839 p7->d.other = ASN1_TYPE_new(); 840 if (p7->d.other == NULL) 841 goto oom; 842 p7->d.other->type = V_ASN1_OCTET_STRING; 843 p7->d.other->value.octet_string = ostr; 844 } 845 846 *p7_out = p7; 847 return 0; 848 849 oom: 850 if (ostr != NULL) 851 ASN1_OCTET_STRING_free(ostr); 852 if (p7 != NULL) 853 PKCS7_free(p7); 854 return ENOMEM; 855 } 856 857 /* ARGSUSED */ 858 krb5_error_code 859 cms_signeddata_create(krb5_context context, 860 pkinit_plg_crypto_context plg_cryptoctx, 861 pkinit_req_crypto_context req_cryptoctx, 862 pkinit_identity_crypto_context id_cryptoctx, 863 int cms_msg_type, 864 int include_certchain, 865 unsigned char *data, 866 unsigned int data_len, 867 unsigned char **signed_data, 868 unsigned int *signed_data_len) 869 { 870 /* Solaris Kerberos */ 871 krb5_error_code retval = KRB5KRB_ERR_GENERIC; 872 PKCS7 *p7 = NULL, *inner_p7 = NULL; 873 PKCS7_SIGNED *p7s = NULL; 874 PKCS7_SIGNER_INFO *p7si = NULL; 875 unsigned char *p; 876 STACK_OF(X509) * cert_stack = NULL; 877 ASN1_OCTET_STRING *digest_attr = NULL; 878 EVP_MD_CTX ctx, ctx2; 879 const EVP_MD *md_tmp = NULL; 880 unsigned char md_data[EVP_MAX_MD_SIZE], md_data2[EVP_MAX_MD_SIZE]; 881 unsigned char *digestInfo_buf = NULL, *abuf = NULL; 882 unsigned int md_len, md_len2, alen, digestInfo_len; 883 STACK_OF(X509_ATTRIBUTE) * sk; 884 unsigned char *sig = NULL; 885 unsigned int sig_len = 0; 886 X509_ALGOR *alg = NULL; 887 ASN1_OCTET_STRING *digest = NULL; 888 unsigned int alg_len = 0, digest_len = 0; 889 unsigned char *y = NULL, *alg_buf = NULL, *digest_buf = NULL; 890 X509 *cert = NULL; 891 ASN1_OBJECT *oid = NULL, *oid_copy; 892 893 /* Solaris Kerberos */ 894 if (signed_data == NULL) 895 return EINVAL; 896 897 if (signed_data_len == NULL) 898 return EINVAL; 899 900 /* start creating PKCS7 data */ 901 if ((p7 = PKCS7_new()) == NULL) 902 goto cleanup; 903 p7->type = OBJ_nid2obj(NID_pkcs7_signed); 904 905 if ((p7s = PKCS7_SIGNED_new()) == NULL) 906 goto cleanup; 907 p7->d.sign = p7s; 908 if (!ASN1_INTEGER_set(p7s->version, 3)) 909 goto cleanup; 910 911 /* create a cert chain that has at least the signer's certificate */ 912 if ((cert_stack = sk_X509_new_null()) == NULL) 913 goto cleanup; 914 915 cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index); 916 if (!include_certchain) { 917 pkiDebug("only including signer's certificate\n"); 918 sk_X509_push(cert_stack, X509_dup(cert)); 919 } else { 920 /* create a cert chain */ 921 X509_STORE *certstore = NULL; 922 X509_STORE_CTX certctx; 923 STACK_OF(X509) *certstack = NULL; 924 char buf[DN_BUF_LEN]; 925 int i = 0, size = 0; 926 927 if ((certstore = X509_STORE_new()) == NULL) 928 goto cleanup; 929 pkiDebug("building certificate chain\n"); 930 X509_STORE_set_verify_cb_func(certstore, openssl_callback); 931 X509_STORE_CTX_init(&certctx, certstore, cert, 932 id_cryptoctx->intermediateCAs); 933 X509_STORE_CTX_trusted_stack(&certctx, id_cryptoctx->trustedCAs); 934 /* Solaris Kerberos */ 935 if (X509_verify_cert(&certctx) <= 0) { 936 pkiDebug("failed to create a certificate chain: %s\n", 937 X509_verify_cert_error_string(X509_STORE_CTX_get_error(&certctx))); 938 if (!sk_X509_num(id_cryptoctx->trustedCAs)) 939 pkiDebug("No trusted CAs found. Check your X509_anchors\n"); 940 goto cleanup; 941 } 942 certstack = X509_STORE_CTX_get1_chain(&certctx); 943 size = sk_X509_num(certstack); 944 pkiDebug("size of certificate chain = %d\n", size); 945 for(i = 0; i < size - 1; i++) { 946 X509 *x = sk_X509_value(certstack, i); 947 X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf)); 948 pkiDebug("cert #%d: %s\n", i, buf); 949 sk_X509_push(cert_stack, X509_dup(x)); 950 } 951 X509_STORE_CTX_cleanup(&certctx); 952 X509_STORE_free(certstore); 953 sk_X509_pop_free(certstack, X509_free); 954 } 955 p7s->cert = cert_stack; 956 957 /* fill-in PKCS7_SIGNER_INFO */ 958 if ((p7si = PKCS7_SIGNER_INFO_new()) == NULL) 959 goto cleanup; 960 if (!ASN1_INTEGER_set(p7si->version, 1)) 961 goto cleanup; 962 if (!X509_NAME_set(&p7si->issuer_and_serial->issuer, 963 X509_get_issuer_name(cert))) 964 goto cleanup; 965 /* because ASN1_INTEGER_set is used to set a 'long' we will do 966 * things the ugly way. */ 967 M_ASN1_INTEGER_free(p7si->issuer_and_serial->serial); 968 if (!(p7si->issuer_and_serial->serial = 969 M_ASN1_INTEGER_dup(X509_get_serialNumber(cert)))) 970 goto cleanup; 971 972 /* will not fill-out EVP_PKEY because it's on the smartcard */ 973 974 /* Set digest algs */ 975 p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha1); 976 977 if (p7si->digest_alg->parameter != NULL) 978 ASN1_TYPE_free(p7si->digest_alg->parameter); 979 if ((p7si->digest_alg->parameter = ASN1_TYPE_new()) == NULL) 980 goto cleanup; 981 p7si->digest_alg->parameter->type = V_ASN1_NULL; 982 983 /* Set sig algs */ 984 if (p7si->digest_enc_alg->parameter != NULL) 985 ASN1_TYPE_free(p7si->digest_enc_alg->parameter); 986 p7si->digest_enc_alg->algorithm = OBJ_nid2obj(NID_sha1WithRSAEncryption); 987 if (!(p7si->digest_enc_alg->parameter = ASN1_TYPE_new())) 988 goto cleanup; 989 p7si->digest_enc_alg->parameter->type = V_ASN1_NULL; 990 991 /* pick the correct oid for the eContentInfo */ 992 oid = pkinit_pkcs7type2oid(plg_cryptoctx, cms_msg_type); 993 if (oid == NULL) 994 goto cleanup; 995 996 if (cms_msg_type == CMS_SIGN_DRAFT9) { 997 /* don't include signed attributes for pa-type 15 request */ 998 abuf = data; 999 alen = data_len; 1000 } else { 1001 /* add signed attributes */ 1002 /* compute sha1 digest over the EncapsulatedContentInfo */ 1003 EVP_MD_CTX_init(&ctx); 1004 EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL); 1005 EVP_DigestUpdate(&ctx, data, data_len); 1006 md_tmp = EVP_MD_CTX_md(&ctx); 1007 EVP_DigestFinal_ex(&ctx, md_data, &md_len); 1008 1009 /* create a message digest attr */ 1010 digest_attr = ASN1_OCTET_STRING_new(); 1011 ASN1_OCTET_STRING_set(digest_attr, md_data, (int)md_len); 1012 PKCS7_add_signed_attribute(p7si, NID_pkcs9_messageDigest, 1013 V_ASN1_OCTET_STRING, (char *) digest_attr); 1014 1015 /* create a content-type attr */ 1016 oid_copy = OBJ_dup(oid); 1017 if (oid_copy == NULL) 1018 goto cleanup2; 1019 PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType, 1020 V_ASN1_OBJECT, oid_copy); 1021 1022 /* create the signature over signed attributes. get DER encoded value */ 1023 /* This is the place where smartcard signature needs to be calculated */ 1024 sk = p7si->auth_attr; 1025 alen = ASN1_item_i2d((ASN1_VALUE *) sk, &abuf, 1026 ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); 1027 if (abuf == NULL) 1028 goto cleanup2; 1029 } 1030 1031 #ifndef WITHOUT_PKCS11 1032 /* Some tokens can only do RSAEncryption without sha1 hash */ 1033 /* to compute sha1WithRSAEncryption, encode the algorithm ID for the hash 1034 * function and the hash value into an ASN.1 value of type DigestInfo 1035 * DigestInfo::=SEQUENCE { 1036 * digestAlgorithm AlgorithmIdentifier, 1037 * digest OCTET STRING } 1038 */ 1039 if (id_cryptoctx->pkcs11_method == 1 && 1040 id_cryptoctx->mech == CKM_RSA_PKCS) { 1041 pkiDebug("mech = CKM_RSA_PKCS\n"); 1042 EVP_MD_CTX_init(&ctx2); 1043 /* if this is not draft9 request, include digest signed attribute */ 1044 if (cms_msg_type != CMS_SIGN_DRAFT9) 1045 EVP_DigestInit_ex(&ctx2, md_tmp, NULL); 1046 else 1047 EVP_DigestInit_ex(&ctx2, EVP_sha1(), NULL); 1048 EVP_DigestUpdate(&ctx2, abuf, alen); 1049 EVP_DigestFinal_ex(&ctx2, md_data2, &md_len2); 1050 1051 alg = X509_ALGOR_new(); 1052 if (alg == NULL) 1053 goto cleanup2; 1054 alg->algorithm = OBJ_nid2obj(NID_sha1); 1055 alg->parameter = NULL; 1056 alg_len = i2d_X509_ALGOR(alg, NULL); 1057 alg_buf = (unsigned char *)malloc(alg_len); 1058 if (alg_buf == NULL) 1059 goto cleanup2; 1060 1061 digest = ASN1_OCTET_STRING_new(); 1062 if (digest == NULL) 1063 goto cleanup2; 1064 ASN1_OCTET_STRING_set(digest, md_data2, (int)md_len2); 1065 digest_len = i2d_ASN1_OCTET_STRING(digest, NULL); 1066 digest_buf = (unsigned char *)malloc(digest_len); 1067 if (digest_buf == NULL) 1068 goto cleanup2; 1069 1070 digestInfo_len = ASN1_object_size(1, (int)(alg_len + digest_len), 1071 V_ASN1_SEQUENCE); 1072 y = digestInfo_buf = (unsigned char *)malloc(digestInfo_len); 1073 if (digestInfo_buf == NULL) 1074 goto cleanup2; 1075 ASN1_put_object(&y, 1, (int)(alg_len + digest_len), V_ASN1_SEQUENCE, 1076 V_ASN1_UNIVERSAL); 1077 i2d_X509_ALGOR(alg, &y); 1078 i2d_ASN1_OCTET_STRING(digest, &y); 1079 #ifdef DEBUG_SIG 1080 pkiDebug("signing buffer\n"); 1081 print_buffer(digestInfo_buf, digestInfo_len); 1082 print_buffer_bin(digestInfo_buf, digestInfo_len, "/tmp/pkcs7_tosign"); 1083 #endif 1084 retval = pkinit_sign_data(context, id_cryptoctx, digestInfo_buf, 1085 digestInfo_len, &sig, &sig_len); 1086 } else 1087 #endif 1088 { 1089 pkiDebug("mech = %s\n", 1090 id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA1_RSA_PKCS" : "FS"); 1091 retval = pkinit_sign_data(context, id_cryptoctx, abuf, alen, 1092 &sig, &sig_len); 1093 } 1094 #ifdef DEBUG_SIG 1095 print_buffer(sig, sig_len); 1096 #endif 1097 if (cms_msg_type != CMS_SIGN_DRAFT9) 1098 free(abuf); 1099 if (retval) 1100 goto cleanup2; 1101 1102 /* Add signature */ 1103 if (!ASN1_STRING_set(p7si->enc_digest, (unsigned char *) sig, 1104 (int)sig_len)) { 1105 unsigned long err = ERR_peek_error(); 1106 retval = KRB5KDC_ERR_PREAUTH_FAILED; 1107 krb5_set_error_message(context, retval, "%s\n", 1108 ERR_error_string(err, NULL)); 1109 pkiDebug("failed to add a signed digest attribute\n"); 1110 goto cleanup2; 1111 } 1112 /* adder signer_info to pkcs7 signed */ 1113 if (!PKCS7_add_signer(p7, p7si)) 1114 goto cleanup2; 1115 1116 /* start on adding data to the pkcs7 signed */ 1117 retval = create_contentinfo(context, oid, data, data_len, &inner_p7); 1118 if (p7s->contents != NULL) 1119 PKCS7_free(p7s->contents); 1120 p7s->contents = inner_p7; 1121 1122 *signed_data_len = i2d_PKCS7(p7, NULL); 1123 if (!(*signed_data_len)) { 1124 unsigned long err = ERR_peek_error(); 1125 retval = KRB5KDC_ERR_PREAUTH_FAILED; 1126 krb5_set_error_message(context, retval, "%s\n", 1127 ERR_error_string(err, NULL)); 1128 pkiDebug("failed to der encode pkcs7\n"); 1129 goto cleanup2; 1130 } 1131 if ((p = *signed_data = 1132 (unsigned char *) malloc((size_t)*signed_data_len)) == NULL) 1133 goto cleanup2; 1134 1135 /* DER encode PKCS7 data */ 1136 retval = i2d_PKCS7(p7, &p); 1137 if (!retval) { 1138 unsigned long err = ERR_peek_error(); 1139 retval = KRB5KDC_ERR_PREAUTH_FAILED; 1140 krb5_set_error_message(context, retval, "%s\n", 1141 ERR_error_string(err, NULL)); 1142 pkiDebug("failed to der encode pkcs7\n"); 1143 goto cleanup2; 1144 } 1145 retval = 0; 1146 1147 #ifdef DEBUG_ASN1 1148 if (cms_msg_type == CMS_SIGN_CLIENT) { 1149 print_buffer_bin(*signed_data, *signed_data_len, 1150 "/tmp/client_pkcs7_signeddata"); 1151 } else { 1152 if (cms_msg_type == CMS_SIGN_SERVER) { 1153 print_buffer_bin(*signed_data, *signed_data_len, 1154 "/tmp/kdc_pkcs7_signeddata"); 1155 } else { 1156 print_buffer_bin(*signed_data, *signed_data_len, 1157 "/tmp/draft9_pkcs7_signeddata"); 1158 } 1159 } 1160 #endif 1161 1162 cleanup2: 1163 if (cms_msg_type != CMS_SIGN_DRAFT9) 1164 EVP_MD_CTX_cleanup(&ctx); 1165 #ifndef WITHOUT_PKCS11 1166 if (id_cryptoctx->pkcs11_method == 1 && 1167 id_cryptoctx->mech == CKM_RSA_PKCS) { 1168 EVP_MD_CTX_cleanup(&ctx2); 1169 if (digest_buf != NULL) 1170 free(digest_buf); 1171 if (digestInfo_buf != NULL) 1172 free(digestInfo_buf); 1173 if (alg_buf != NULL) 1174 free(alg_buf); 1175 if (digest != NULL) 1176 ASN1_OCTET_STRING_free(digest); 1177 } 1178 #endif 1179 if (alg != NULL) 1180 X509_ALGOR_free(alg); 1181 cleanup: 1182 if (p7 != NULL) 1183 PKCS7_free(p7); 1184 if (sig != NULL) 1185 free(sig); 1186 1187 return retval; 1188 } 1189 1190 krb5_error_code 1191 cms_signeddata_verify(krb5_context context, 1192 pkinit_plg_crypto_context plgctx, 1193 pkinit_req_crypto_context reqctx, 1194 pkinit_identity_crypto_context idctx, 1195 int cms_msg_type, 1196 int require_crl_checking, 1197 unsigned char *signed_data, 1198 unsigned int signed_data_len, 1199 unsigned char **data, 1200 unsigned int *data_len, 1201 unsigned char **authz_data, 1202 unsigned int *authz_data_len) 1203 { 1204 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; 1205 PKCS7 *p7 = NULL; 1206 BIO *out = NULL; 1207 int flags = PKCS7_NOVERIFY, i = 0; 1208 unsigned int vflags = 0, size = 0; 1209 const unsigned char *p = signed_data; 1210 STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL; 1211 PKCS7_SIGNER_INFO *si = NULL; 1212 X509 *x = NULL; 1213 X509_STORE *store = NULL; 1214 X509_STORE_CTX cert_ctx; 1215 STACK_OF(X509) *intermediateCAs = NULL; 1216 STACK_OF(X509_CRL) *revoked = NULL; 1217 STACK_OF(X509) *verified_chain = NULL; 1218 ASN1_OBJECT *oid = NULL; 1219 krb5_external_principal_identifier **krb5_verified_chain = NULL; 1220 krb5_data *authz = NULL; 1221 char buf[DN_BUF_LEN]; 1222 1223 #ifdef DEBUG_ASN1 1224 print_buffer_bin(signed_data, signed_data_len, 1225 "/tmp/client_received_pkcs7_signeddata"); 1226 #endif 1227 1228 oid = pkinit_pkcs7type2oid(plgctx, cms_msg_type); 1229 if (oid == NULL) 1230 goto cleanup; 1231 1232 /* decode received PKCS7 message */ 1233 if ((p7 = d2i_PKCS7(NULL, &p, (int)signed_data_len)) == NULL) { 1234 unsigned long err = ERR_peek_error(); 1235 krb5_set_error_message(context, retval, "%s\n", 1236 ERR_error_string(err, NULL)); 1237 pkiDebug("%s: failed to decode message: %s\n", 1238 __FUNCTION__, ERR_error_string(err, NULL)); 1239 goto cleanup; 1240 } 1241 1242 /* verify that the received message is PKCS7 SignedData message */ 1243 if (OBJ_obj2nid(p7->type) != NID_pkcs7_signed) { 1244 pkiDebug("Expected id-signedData PKCS7 msg (received type = %d)\n", 1245 OBJ_obj2nid(p7->type)); 1246 krb5_set_error_message(context, retval, "wrong oid\n"); 1247 goto cleanup; 1248 } 1249 1250 /* setup to verify X509 certificate used to sign PKCS7 message */ 1251 if (!(store = X509_STORE_new())) 1252 goto cleanup; 1253 1254 /* check if we are inforcing CRL checking */ 1255 vflags = X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; 1256 if (require_crl_checking) 1257 X509_STORE_set_verify_cb_func(store, openssl_callback); 1258 else 1259 X509_STORE_set_verify_cb_func(store, openssl_callback_ignore_crls); 1260 X509_STORE_set_flags(store, vflags); 1261 1262 /* get the signer's information from the PKCS7 message */ 1263 if ((si_sk = PKCS7_get_signer_info(p7)) == NULL) 1264 goto cleanup; 1265 if ((si = sk_PKCS7_SIGNER_INFO_value(si_sk, 0)) == NULL) 1266 goto cleanup; 1267 if ((x = PKCS7_cert_from_signer_info(p7, si)) == NULL) 1268 goto cleanup; 1269 1270 /* create available CRL information (get local CRLs and include CRLs 1271 * received in the PKCS7 message 1272 */ 1273 if (idctx->revoked == NULL) 1274 revoked = p7->d.sign->crl; 1275 else if (p7->d.sign->crl == NULL) 1276 revoked = idctx->revoked; 1277 else { 1278 size = sk_X509_CRL_num(idctx->revoked); 1279 revoked = sk_X509_CRL_new_null(); 1280 for (i = 0; i < size; i++) 1281 sk_X509_CRL_push(revoked, sk_X509_CRL_value(idctx->revoked, i)); 1282 size = sk_X509_CRL_num(p7->d.sign->crl); 1283 for (i = 0; i < size; i++) 1284 sk_X509_CRL_push(revoked, sk_X509_CRL_value(p7->d.sign->crl, i)); 1285 } 1286 1287 /* create available intermediate CAs chains (get local intermediateCAs and 1288 * include the CA chain received in the PKCS7 message 1289 */ 1290 if (idctx->intermediateCAs == NULL) 1291 intermediateCAs = p7->d.sign->cert; 1292 else if (p7->d.sign->cert == NULL) 1293 intermediateCAs = idctx->intermediateCAs; 1294 else { 1295 size = sk_X509_num(idctx->intermediateCAs); 1296 intermediateCAs = sk_X509_new_null(); 1297 for (i = 0; i < size; i++) { 1298 sk_X509_push(intermediateCAs, 1299 sk_X509_value(idctx->intermediateCAs, i)); 1300 } 1301 size = sk_X509_num(p7->d.sign->cert); 1302 for (i = 0; i < size; i++) { 1303 sk_X509_push(intermediateCAs, sk_X509_value(p7->d.sign->cert, i)); 1304 } 1305 } 1306 1307 /* initialize x509 context with the received certificate and 1308 * trusted and intermediate CA chains and CRLs 1309 */ 1310 if (!X509_STORE_CTX_init(&cert_ctx, store, x, intermediateCAs)) 1311 goto cleanup; 1312 1313 X509_STORE_CTX_set0_crls(&cert_ctx, revoked); 1314 1315 /* add trusted CAs certificates for cert verification */ 1316 if (idctx->trustedCAs != NULL) 1317 X509_STORE_CTX_trusted_stack(&cert_ctx, idctx->trustedCAs); 1318 else { 1319 pkiDebug("unable to find any trusted CAs\n"); 1320 goto cleanup; 1321 } 1322 #ifdef DEBUG_CERTCHAIN 1323 if (intermediateCAs != NULL) { 1324 size = sk_X509_num(intermediateCAs); 1325 pkiDebug("untrusted cert chain of size %d\n", size); 1326 for (i = 0; i < size; i++) { 1327 X509_NAME_oneline(X509_get_subject_name( 1328 sk_X509_value(intermediateCAs, i)), buf, sizeof(buf)); 1329 pkiDebug("cert #%d: %s\n", i, buf); 1330 } 1331 } 1332 if (idctx->trustedCAs != NULL) { 1333 size = sk_X509_num(idctx->trustedCAs); 1334 pkiDebug("trusted cert chain of size %d\n", size); 1335 for (i = 0; i < size; i++) { 1336 X509_NAME_oneline(X509_get_subject_name( 1337 sk_X509_value(idctx->trustedCAs, i)), buf, sizeof(buf)); 1338 pkiDebug("cert #%d: %s\n", i, buf); 1339 } 1340 } 1341 if (revoked != NULL) { 1342 size = sk_X509_CRL_num(revoked); 1343 pkiDebug("CRL chain of size %d\n", size); 1344 for (i = 0; i < size; i++) { 1345 X509_CRL *crl = sk_X509_CRL_value(revoked, i); 1346 X509_NAME_oneline(X509_CRL_get_issuer(crl), buf, sizeof(buf)); 1347 pkiDebug("crls by CA #%d: %s\n", i , buf); 1348 } 1349 } 1350 #endif 1351 1352 i = X509_verify_cert(&cert_ctx); 1353 if (i <= 0) { 1354 int j = X509_STORE_CTX_get_error(&cert_ctx); 1355 1356 reqctx->received_cert = X509_dup(cert_ctx.current_cert); 1357 switch(j) { 1358 case X509_V_ERR_CERT_REVOKED: 1359 retval = KRB5KDC_ERR_REVOKED_CERTIFICATE; 1360 break; 1361 case X509_V_ERR_UNABLE_TO_GET_CRL: 1362 retval = KRB5KDC_ERR_REVOCATION_STATUS_UNKNOWN; 1363 break; 1364 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: 1365 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: 1366 retval = KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE; 1367 break; 1368 default: 1369 retval = KRB5KDC_ERR_INVALID_CERTIFICATE; 1370 } 1371 X509_NAME_oneline(X509_get_subject_name( 1372 reqctx->received_cert), buf, sizeof(buf)); 1373 pkiDebug("problem with cert DN = %s (error=%d) %s\n", buf, j, 1374 X509_verify_cert_error_string(j)); 1375 krb5_set_error_message(context, retval, "%s\n", 1376 X509_verify_cert_error_string(j)); 1377 #ifdef DEBUG_CERTCHAIN 1378 size = sk_X509_num(p7->d.sign->cert); 1379 pkiDebug("received cert chain of size %d\n", size); 1380 for (j = 0; j < size; j++) { 1381 X509 *tmp_cert = sk_X509_value(p7->d.sign->cert, j); 1382 X509_NAME_oneline(X509_get_subject_name(tmp_cert), buf, sizeof(buf)); 1383 pkiDebug("cert #%d: %s\n", j, buf); 1384 } 1385 #endif 1386 } else { 1387 /* retrieve verified certificate chain */ 1388 if (cms_msg_type == CMS_SIGN_CLIENT || cms_msg_type == CMS_SIGN_DRAFT9) 1389 verified_chain = X509_STORE_CTX_get1_chain(&cert_ctx); 1390 } 1391 X509_STORE_CTX_cleanup(&cert_ctx); 1392 if (i <= 0) 1393 goto cleanup; 1394 1395 out = BIO_new(BIO_s_mem()); 1396 if (cms_msg_type == CMS_SIGN_DRAFT9) 1397 flags |= PKCS7_NOATTR; 1398 if (PKCS7_verify(p7, NULL, store, NULL, out, flags)) { 1399 int valid_oid = 0; 1400 1401 if (!OBJ_cmp(p7->d.sign->contents->type, oid)) 1402 valid_oid = 1; 1403 else if (cms_msg_type == CMS_SIGN_DRAFT9) { 1404 /* 1405 * Various implementations of the pa-type 15 request use 1406 * different OIDS. We check that the returned object 1407 * has any of the acceptable OIDs 1408 */ 1409 ASN1_OBJECT *client_oid = NULL, *server_oid = NULL, *rsa_oid = NULL; 1410 client_oid = pkinit_pkcs7type2oid(plgctx, CMS_SIGN_CLIENT); 1411 server_oid = pkinit_pkcs7type2oid(plgctx, CMS_SIGN_SERVER); 1412 rsa_oid = pkinit_pkcs7type2oid(plgctx, CMS_ENVEL_SERVER); 1413 if (!OBJ_cmp(p7->d.sign->contents->type, client_oid) || 1414 !OBJ_cmp(p7->d.sign->contents->type, server_oid) || 1415 !OBJ_cmp(p7->d.sign->contents->type, rsa_oid)) 1416 valid_oid = 1; 1417 } 1418 1419 if (valid_oid) 1420 pkiDebug("PKCS7 Verification successful\n"); 1421 else { 1422 pkiDebug("wrong oid in eContentType\n"); 1423 print_buffer((unsigned char *)p7->d.sign->contents->type->data, 1424 (unsigned int)p7->d.sign->contents->type->length); 1425 retval = KRB5KDC_ERR_PREAUTH_FAILED; 1426 krb5_set_error_message(context, retval, "wrong oid\n"); 1427 goto cleanup; 1428 } 1429 } 1430 else { 1431 unsigned long err = ERR_peek_error(); 1432 switch(ERR_GET_REASON(err)) { 1433 case PKCS7_R_DIGEST_FAILURE: 1434 retval = KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED; 1435 break; 1436 case PKCS7_R_SIGNATURE_FAILURE: 1437 default: 1438 retval = KRB5KDC_ERR_INVALID_SIG; 1439 } 1440 pkiDebug("PKCS7 Verification failure\n"); 1441 krb5_set_error_message(context, retval, "%s\n", 1442 ERR_error_string(err, NULL)); 1443 goto cleanup; 1444 } 1445 1446 /* transfer the data from PKCS7 message into return buffer */ 1447 for (size = 0;;) { 1448 if ((*data = realloc(*data, size + 1024 * 10)) == NULL) 1449 goto cleanup; 1450 i = BIO_read(out, &((*data)[size]), 1024 * 10); 1451 if (i <= 0) 1452 break; 1453 else 1454 size += i; 1455 } 1456 *data_len = size; 1457 1458 reqctx->received_cert = X509_dup(x); 1459 1460 /* generate authorization data */ 1461 if (cms_msg_type == CMS_SIGN_CLIENT || cms_msg_type == CMS_SIGN_DRAFT9) { 1462 1463 if (authz_data == NULL || authz_data_len == NULL) 1464 goto out; 1465 1466 *authz_data = NULL; 1467 retval = create_identifiers_from_stack(verified_chain, 1468 &krb5_verified_chain); 1469 if (retval) { 1470 pkiDebug("create_identifiers_from_stack failed\n"); 1471 goto cleanup; 1472 } 1473 1474 retval = k5int_encode_krb5_td_trusted_certifiers((const krb5_external_principal_identifier **)krb5_verified_chain, &authz); 1475 if (retval) { 1476 pkiDebug("encode_krb5_td_trusted_certifiers failed\n"); 1477 goto cleanup; 1478 } 1479 #ifdef DEBUG_ASN1 1480 print_buffer_bin((unsigned char *)authz->data, authz->length, 1481 "/tmp/kdc_ad_initial_verified_cas"); 1482 #endif 1483 *authz_data = (unsigned char *)malloc(authz->length); 1484 if (*authz_data == NULL) { 1485 retval = ENOMEM; 1486 goto cleanup; 1487 } 1488 (void) memcpy(*authz_data, authz->data, authz->length); 1489 *authz_data_len = authz->length; 1490 } 1491 out: 1492 retval = 0; 1493 1494 cleanup: 1495 if (out != NULL) 1496 BIO_free(out); 1497 if (store != NULL) 1498 X509_STORE_free(store); 1499 if (p7 != NULL) { 1500 if (idctx->intermediateCAs != NULL && p7->d.sign->cert) 1501 sk_X509_free(intermediateCAs); 1502 if (idctx->revoked != NULL && p7->d.sign->crl) 1503 sk_X509_CRL_free(revoked); 1504 PKCS7_free(p7); 1505 } 1506 if (verified_chain != NULL) 1507 sk_X509_pop_free(verified_chain, X509_free); 1508 if (krb5_verified_chain != NULL) 1509 free_krb5_external_principal_identifier(&krb5_verified_chain); 1510 if (authz != NULL) 1511 krb5_free_data(context, authz); 1512 1513 return retval; 1514 } 1515 1516 krb5_error_code 1517 cms_envelopeddata_create(krb5_context context, 1518 pkinit_plg_crypto_context plgctx, 1519 pkinit_req_crypto_context reqctx, 1520 pkinit_identity_crypto_context idctx, 1521 krb5_preauthtype pa_type, 1522 int include_certchain, 1523 unsigned char *key_pack, 1524 unsigned int key_pack_len, 1525 unsigned char **out, 1526 unsigned int *out_len) 1527 { 1528 1529 /* Solaris Kerberos */ 1530 krb5_error_code retval = KRB5KRB_ERR_GENERIC; 1531 PKCS7 *p7 = NULL; 1532 BIO *in = NULL; 1533 unsigned char *p = NULL, *signed_data = NULL, *enc_data = NULL; 1534 int signed_data_len = 0, enc_data_len = 0, flags = PKCS7_BINARY; 1535 STACK_OF(X509) *encerts = NULL; 1536 const EVP_CIPHER *cipher = NULL; 1537 int cms_msg_type; 1538 1539 /* create the PKCS7 SignedData portion of the PKCS7 EnvelopedData */ 1540 switch ((int)pa_type) { 1541 case KRB5_PADATA_PK_AS_REQ_OLD: 1542 case KRB5_PADATA_PK_AS_REP_OLD: 1543 cms_msg_type = CMS_SIGN_DRAFT9; 1544 break; 1545 case KRB5_PADATA_PK_AS_REQ: 1546 cms_msg_type = CMS_ENVEL_SERVER; 1547 break; 1548 default: 1549 /* Solaris Kerberos */ 1550 retval = EINVAL; 1551 goto cleanup; 1552 } 1553 1554 retval = cms_signeddata_create(context, plgctx, reqctx, idctx, 1555 cms_msg_type, include_certchain, key_pack, key_pack_len, 1556 &signed_data, (unsigned int *)&signed_data_len); 1557 if (retval) { 1558 pkiDebug("failed to create pkcs7 signed data\n"); 1559 goto cleanup; 1560 } 1561 1562 /* check we have client's certificate */ 1563 if (reqctx->received_cert == NULL) { 1564 retval = KRB5KDC_ERR_PREAUTH_FAILED; 1565 goto cleanup; 1566 } 1567 encerts = sk_X509_new_null(); 1568 sk_X509_push(encerts, reqctx->received_cert); 1569 1570 cipher = EVP_des_ede3_cbc(); 1571 in = BIO_new(BIO_s_mem()); 1572 switch (pa_type) { 1573 case KRB5_PADATA_PK_AS_REQ: 1574 prepare_enc_data(signed_data, signed_data_len, &enc_data, 1575 &enc_data_len); 1576 retval = BIO_write(in, enc_data, enc_data_len); 1577 if (retval != enc_data_len) { 1578 pkiDebug("BIO_write only wrote %d\n", retval); 1579 goto cleanup; 1580 } 1581 break; 1582 case KRB5_PADATA_PK_AS_REP_OLD: 1583 case KRB5_PADATA_PK_AS_REQ_OLD: 1584 retval = BIO_write(in, signed_data, signed_data_len); 1585 if (retval != signed_data_len) { 1586 pkiDebug("BIO_write only wrote %d\n", retval); 1587 /* Solaris Kerberos */ 1588 retval = KRB5KRB_ERR_GENERIC; 1589 goto cleanup; 1590 } 1591 break; 1592 default: 1593 retval = -1; 1594 goto cleanup; 1595 } 1596 1597 p7 = PKCS7_encrypt(encerts, in, cipher, flags); 1598 if (p7 == NULL) { 1599 pkiDebug("failed to encrypt PKCS7 object\n"); 1600 retval = -1; 1601 goto cleanup; 1602 } 1603 switch (pa_type) { 1604 case KRB5_PADATA_PK_AS_REQ: 1605 p7->d.enveloped->enc_data->content_type = 1606 OBJ_nid2obj(NID_pkcs7_signed); 1607 break; 1608 case KRB5_PADATA_PK_AS_REP_OLD: 1609 case KRB5_PADATA_PK_AS_REQ_OLD: 1610 p7->d.enveloped->enc_data->content_type = 1611 OBJ_nid2obj(NID_pkcs7_data); 1612 break; 1613 } 1614 1615 *out_len = i2d_PKCS7(p7, NULL); 1616 if (!*out_len || (p = *out = (unsigned char *)malloc(*out_len)) == NULL) { 1617 retval = ENOMEM; 1618 goto cleanup; 1619 } 1620 retval = i2d_PKCS7(p7, &p); 1621 if (!retval) { 1622 pkiDebug("unable to write pkcs7 object\n"); 1623 goto cleanup; 1624 } 1625 retval = 0; 1626 1627 #ifdef DEBUG_ASN1 1628 print_buffer_bin(*out, *out_len, "/tmp/kdc_enveloped_data"); 1629 #endif 1630 1631 cleanup: 1632 if (p7 != NULL) 1633 PKCS7_free(p7); 1634 if (in != NULL) 1635 BIO_free(in); 1636 if (signed_data != NULL) 1637 free(signed_data); 1638 if (enc_data != NULL) 1639 free(enc_data); 1640 if (encerts != NULL) 1641 sk_X509_free(encerts); 1642 1643 return retval; 1644 } 1645 1646 krb5_error_code 1647 cms_envelopeddata_verify(krb5_context context, 1648 pkinit_plg_crypto_context plg_cryptoctx, 1649 pkinit_req_crypto_context req_cryptoctx, 1650 pkinit_identity_crypto_context id_cryptoctx, 1651 krb5_preauthtype pa_type, 1652 int require_crl_checking, 1653 unsigned char *enveloped_data, 1654 unsigned int enveloped_data_len, 1655 unsigned char **data, 1656 unsigned int *data_len) 1657 { 1658 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; 1659 PKCS7 *p7 = NULL; 1660 BIO *out = NULL; 1661 int i = 0; 1662 unsigned int size = 0; 1663 const unsigned char *p = enveloped_data; 1664 unsigned int tmp_buf_len = 0, tmp_buf2_len = 0, vfy_buf_len = 0; 1665 unsigned char *tmp_buf = NULL, *tmp_buf2 = NULL, *vfy_buf = NULL; 1666 int msg_type = 0; 1667 1668 #ifdef DEBUG_ASN1 1669 print_buffer_bin(enveloped_data, enveloped_data_len, 1670 "/tmp/client_envelopeddata"); 1671 #endif 1672 /* decode received PKCS7 message */ 1673 if ((p7 = d2i_PKCS7(NULL, &p, (int)enveloped_data_len)) == NULL) { 1674 unsigned long err = ERR_peek_error(); 1675 pkiDebug("failed to decode pkcs7\n"); 1676 krb5_set_error_message(context, retval, "%s\n", 1677 ERR_error_string(err, NULL)); 1678 goto cleanup; 1679 } 1680 1681 /* verify that the received message is PKCS7 EnvelopedData message */ 1682 if (OBJ_obj2nid(p7->type) != NID_pkcs7_enveloped) { 1683 pkiDebug("Expected id-enveloped PKCS7 msg (received type = %d)\n", 1684 OBJ_obj2nid(p7->type)); 1685 krb5_set_error_message(context, retval, "wrong oid\n"); 1686 goto cleanup; 1687 } 1688 1689 /* decrypt received PKCS7 message */ 1690 out = BIO_new(BIO_s_mem()); 1691 if (pkcs7_decrypt(context, id_cryptoctx, p7, out)) { 1692 pkiDebug("PKCS7 decryption successful\n"); 1693 } else { 1694 unsigned long err = ERR_peek_error(); 1695 if (err != 0) 1696 krb5_set_error_message(context, retval, "%s\n", 1697 ERR_error_string(err, NULL)); 1698 pkiDebug("PKCS7 decryption failed\n"); 1699 goto cleanup; 1700 } 1701 1702 /* transfer the decoded PKCS7 SignedData message into a separate buffer */ 1703 for (;;) { 1704 if ((tmp_buf = realloc(tmp_buf, size + 1024 * 10)) == NULL) 1705 goto cleanup; 1706 i = BIO_read(out, &(tmp_buf[size]), 1024 * 10); 1707 if (i <= 0) 1708 break; 1709 else 1710 size += i; 1711 } 1712 tmp_buf_len = size; 1713 1714 #ifdef DEBUG_ASN1 1715 print_buffer_bin(tmp_buf, tmp_buf_len, "/tmp/client_enc_keypack"); 1716 #endif 1717 /* verify PKCS7 SignedData message */ 1718 switch (pa_type) { 1719 case KRB5_PADATA_PK_AS_REP: 1720 msg_type = CMS_ENVEL_SERVER; 1721 1722 break; 1723 case KRB5_PADATA_PK_AS_REP_OLD: 1724 msg_type = CMS_SIGN_DRAFT9; 1725 break; 1726 default: 1727 pkiDebug("%s: unrecognized pa_type = %d\n", __FUNCTION__, pa_type); 1728 retval = KRB5KDC_ERR_PREAUTH_FAILED; 1729 goto cleanup; 1730 } 1731 /* 1732 * If this is the RFC style, wrap the signed data to make 1733 * decoding easier in the verify routine. 1734 * For draft9-compatible, we don't do anything because it 1735 * is already wrapped. 1736 */ 1737 #ifdef LONGHORN_BETA_COMPAT 1738 /* 1739 * The Longhorn server returns the expected RFC-style data, but 1740 * it is missing the sequence tag and length, so it requires 1741 * special processing when wrapping. 1742 * This will hopefully be fixed before the final release and 1743 * this can all be removed. 1744 */ 1745 if (msg_type == CMS_ENVEL_SERVER || longhorn == 1) { 1746 retval = wrap_signeddata(tmp_buf, tmp_buf_len, 1747 &tmp_buf2, &tmp_buf2_len, longhorn); 1748 if (retval) { 1749 pkiDebug("failed to encode signeddata\n"); 1750 goto cleanup; 1751 } 1752 vfy_buf = tmp_buf2; 1753 vfy_buf_len = tmp_buf2_len; 1754 1755 } else { 1756 vfy_buf = tmp_buf; 1757 vfy_buf_len = tmp_buf_len; 1758 } 1759 #else 1760 if (msg_type == CMS_ENVEL_SERVER) { 1761 retval = wrap_signeddata(tmp_buf, tmp_buf_len, 1762 &tmp_buf2, &tmp_buf2_len); 1763 if (retval) { 1764 pkiDebug("failed to encode signeddata\n"); 1765 goto cleanup; 1766 } 1767 vfy_buf = tmp_buf2; 1768 vfy_buf_len = tmp_buf2_len; 1769 1770 } else { 1771 vfy_buf = tmp_buf; 1772 vfy_buf_len = tmp_buf_len; 1773 } 1774 #endif 1775 1776 #ifdef DEBUG_ASN1 1777 print_buffer_bin(vfy_buf, vfy_buf_len, "/tmp/client_enc_keypack2"); 1778 #endif 1779 1780 retval = cms_signeddata_verify(context, plg_cryptoctx, req_cryptoctx, 1781 id_cryptoctx, msg_type, 1782 require_crl_checking, 1783 vfy_buf, vfy_buf_len, 1784 data, data_len, NULL, NULL); 1785 1786 if (!retval) 1787 pkiDebug("PKCS7 Verification Success\n"); 1788 else { 1789 pkiDebug("PKCS7 Verification Failure\n"); 1790 goto cleanup; 1791 } 1792 1793 retval = 0; 1794 1795 cleanup: 1796 1797 if (p7 != NULL) 1798 PKCS7_free(p7); 1799 if (out != NULL) 1800 BIO_free(out); 1801 if (tmp_buf != NULL) 1802 free(tmp_buf); 1803 if (tmp_buf2 != NULL) 1804 free(tmp_buf2); 1805 1806 return retval; 1807 } 1808 1809 /* ARGSUSED */ 1810 static krb5_error_code 1811 crypto_retrieve_X509_sans(krb5_context context, 1812 pkinit_plg_crypto_context plgctx, 1813 pkinit_req_crypto_context reqctx, 1814 X509 *cert, 1815 krb5_principal **princs_ret, 1816 krb5_principal **upn_ret, 1817 unsigned char ***dns_ret) 1818 { 1819 krb5_error_code retval = EINVAL; 1820 char buf[DN_BUF_LEN]; 1821 int p = 0, u = 0, d = 0; 1822 krb5_principal *princs = NULL; 1823 krb5_principal *upns = NULL; 1824 unsigned char **dnss = NULL; 1825 int i, num_found = 0; 1826 1827 if (princs_ret == NULL && upn_ret == NULL && dns_ret == NULL) { 1828 pkiDebug("%s: nowhere to return any values!\n", __FUNCTION__); 1829 return retval; 1830 } 1831 1832 if (cert == NULL) { 1833 pkiDebug("%s: no certificate!\n", __FUNCTION__); 1834 return retval; 1835 } 1836 1837 X509_NAME_oneline(X509_get_subject_name(cert), 1838 buf, sizeof(buf)); 1839 pkiDebug("%s: looking for SANs in cert = %s\n", __FUNCTION__, buf); 1840 1841 if ((i = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1)) >= 0) { 1842 X509_EXTENSION *ext = NULL; 1843 GENERAL_NAMES *ialt = NULL; 1844 GENERAL_NAME *gen = NULL; 1845 int ret = 0; 1846 unsigned int num_sans = 0; 1847 1848 if (!(ext = X509_get_ext(cert, i)) || !(ialt = X509V3_EXT_d2i(ext))) { 1849 pkiDebug("%s: found no subject alt name extensions\n", 1850 __FUNCTION__); 1851 goto cleanup; 1852 } 1853 num_sans = sk_GENERAL_NAME_num(ialt); 1854 1855 pkiDebug("%s: found %d subject alt name extension(s)\n", 1856 __FUNCTION__, num_sans); 1857 1858 /* OK, we're likely returning something. Allocate return values */ 1859 if (princs_ret != NULL) { 1860 princs = calloc(num_sans + 1, sizeof(krb5_principal)); 1861 if (princs == NULL) { 1862 retval = ENOMEM; 1863 goto cleanup; 1864 } 1865 } 1866 if (upn_ret != NULL) { 1867 upns = calloc(num_sans + 1, sizeof(krb5_principal)); 1868 if (upns == NULL) { 1869 retval = ENOMEM; 1870 goto cleanup; 1871 } 1872 } 1873 if (dns_ret != NULL) { 1874 dnss = calloc(num_sans + 1, sizeof(*dnss)); 1875 if (dnss == NULL) { 1876 retval = ENOMEM; 1877 goto cleanup; 1878 } 1879 } 1880 1881 for (i = 0; i < num_sans; i++) { 1882 krb5_data name = { 0, 0, NULL }; 1883 1884 gen = sk_GENERAL_NAME_value(ialt, i); 1885 switch (gen->type) { 1886 case GEN_OTHERNAME: 1887 name.length = gen->d.otherName->value->value.sequence->length; 1888 name.data = (char *)gen->d.otherName->value->value.sequence->data; 1889 if (princs != NULL 1890 && OBJ_cmp(plgctx->id_pkinit_san, 1891 gen->d.otherName->type_id) == 0) { 1892 #ifdef DEBUG_ASN1 1893 print_buffer_bin((unsigned char *)name.data, name.length, 1894 "/tmp/pkinit_san"); 1895 #endif 1896 ret = k5int_decode_krb5_principal_name(&name, &princs[p]); 1897 if (ret) { 1898 pkiDebug("%s: failed decoding pkinit san value\n", 1899 __FUNCTION__); 1900 } else { 1901 p++; 1902 num_found++; 1903 } 1904 } else if (upns != NULL 1905 && OBJ_cmp(plgctx->id_ms_san_upn, 1906 gen->d.otherName->type_id) == 0) { 1907 ret = krb5_parse_name(context, name.data, &upns[u]); 1908 if (ret) { 1909 pkiDebug("%s: failed parsing ms-upn san value\n", 1910 __FUNCTION__); 1911 } else { 1912 u++; 1913 num_found++; 1914 } 1915 } else { 1916 pkiDebug("%s: unrecognized othername oid in SAN\n", 1917 __FUNCTION__); 1918 continue; 1919 } 1920 1921 break; 1922 case GEN_DNS: 1923 if (dnss != NULL) { 1924 pkiDebug("%s: found dns name = %s\n", 1925 __FUNCTION__, gen->d.dNSName->data); 1926 dnss[d] = (unsigned char *) 1927 strdup((char *)gen->d.dNSName->data); 1928 if (dnss[d] == NULL) { 1929 pkiDebug("%s: failed to duplicate dns name\n", 1930 __FUNCTION__); 1931 } else { 1932 d++; 1933 num_found++; 1934 } 1935 } 1936 break; 1937 default: 1938 pkiDebug("%s: SAN type = %d expecting %d\n", 1939 __FUNCTION__, gen->type, GEN_OTHERNAME); 1940 } 1941 } 1942 sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free); 1943 } 1944 1945 retval = 0; 1946 if (princs) 1947 *princs_ret = princs; 1948 if (upns) 1949 *upn_ret = upns; 1950 if (dnss) 1951 *dns_ret = dnss; 1952 1953 cleanup: 1954 if (retval) { 1955 if (princs != NULL) { 1956 for (i = 0; princs[i] != NULL; i++) 1957 krb5_free_principal(context, princs[i]); 1958 free(princs); 1959 } 1960 if (upns != NULL) { 1961 for (i = 0; upns[i] != NULL; i++) 1962 krb5_free_principal(context, upns[i]); 1963 free(upns); 1964 } 1965 if (dnss != NULL) { 1966 for (i = 0; dnss[i] != NULL; i++) 1967 free(dnss[i]); 1968 free(dnss); 1969 } 1970 } 1971 return retval; 1972 } 1973 1974 /* ARGSUSED */ 1975 krb5_error_code 1976 crypto_retrieve_cert_sans(krb5_context context, 1977 pkinit_plg_crypto_context plgctx, 1978 pkinit_req_crypto_context reqctx, 1979 pkinit_identity_crypto_context idctx, 1980 krb5_principal **princs_ret, 1981 krb5_principal **upn_ret, 1982 unsigned char ***dns_ret) 1983 { 1984 krb5_error_code retval = EINVAL; 1985 1986 if (reqctx->received_cert == NULL) { 1987 pkiDebug("%s: No certificate!\n", __FUNCTION__); 1988 return retval; 1989 } 1990 1991 return crypto_retrieve_X509_sans(context, plgctx, reqctx, 1992 reqctx->received_cert, princs_ret, 1993 upn_ret, dns_ret); 1994 } 1995 1996 /* ARGSUSED */ 1997 krb5_error_code 1998 crypto_check_cert_eku(krb5_context context, 1999 pkinit_plg_crypto_context plgctx, 2000 pkinit_req_crypto_context reqctx, 2001 pkinit_identity_crypto_context idctx, 2002 int checking_kdc_cert, 2003 int allow_secondary_usage, 2004 int *valid_eku) 2005 { 2006 char buf[DN_BUF_LEN]; 2007 int found_eku = 0; 2008 krb5_error_code retval = EINVAL; 2009 int i; 2010 2011 /* Solaris Kerberos */ 2012 if (valid_eku == NULL) 2013 return retval; 2014 2015 *valid_eku = 0; 2016 if (reqctx->received_cert == NULL) 2017 goto cleanup; 2018 2019 X509_NAME_oneline(X509_get_subject_name(reqctx->received_cert), 2020 buf, sizeof(buf)); 2021 pkiDebug("%s: looking for EKUs in cert = %s\n", __FUNCTION__, buf); 2022 2023 if ((i = X509_get_ext_by_NID(reqctx->received_cert, 2024 NID_ext_key_usage, -1)) >= 0) { 2025 EXTENDED_KEY_USAGE *extusage; 2026 2027 extusage = X509_get_ext_d2i(reqctx->received_cert, NID_ext_key_usage, 2028 NULL, NULL); 2029 if (extusage) { 2030 pkiDebug("%s: found eku info in the cert\n", __FUNCTION__); 2031 for (i = 0; found_eku == 0 && i < sk_ASN1_OBJECT_num(extusage); i++) { 2032 ASN1_OBJECT *tmp_oid; 2033 2034 tmp_oid = sk_ASN1_OBJECT_value(extusage, i); 2035 pkiDebug("%s: checking eku %d of %d, allow_secondary = %d\n", 2036 __FUNCTION__, i+1, sk_ASN1_OBJECT_num(extusage), 2037 allow_secondary_usage); 2038 if (checking_kdc_cert) { 2039 if ((OBJ_cmp(tmp_oid, plgctx->id_pkinit_KPKdc) == 0) 2040 || (allow_secondary_usage 2041 && OBJ_cmp(tmp_oid, plgctx->id_kp_serverAuth) == 0)) 2042 found_eku = 1; 2043 } else { 2044 if ((OBJ_cmp(tmp_oid, plgctx->id_pkinit_KPClientAuth) == 0) 2045 || (allow_secondary_usage 2046 && OBJ_cmp(tmp_oid, plgctx->id_ms_kp_sc_logon) == 0)) 2047 found_eku = 1; 2048 } 2049 } 2050 } 2051 EXTENDED_KEY_USAGE_free(extusage); 2052 2053 if (found_eku) { 2054 ASN1_BIT_STRING *usage = NULL; 2055 pkiDebug("%s: found acceptable EKU, checking for digitalSignature\n", __FUNCTION__); 2056 2057 /* check that digitalSignature KeyUsage is present */ 2058 if ((usage = X509_get_ext_d2i(reqctx->received_cert, 2059 NID_key_usage, NULL, NULL))) { 2060 2061 if (!ku_reject(reqctx->received_cert, 2062 X509v3_KU_DIGITAL_SIGNATURE)) { 2063 pkiDebug("%s: found digitalSignature KU\n", 2064 __FUNCTION__); 2065 *valid_eku = 1; 2066 } else 2067 pkiDebug("%s: didn't find digitalSignature KU\n", 2068 __FUNCTION__); 2069 } 2070 ASN1_BIT_STRING_free(usage); 2071 } 2072 } 2073 retval = 0; 2074 cleanup: 2075 pkiDebug("%s: returning retval %d, valid_eku %d\n", 2076 __FUNCTION__, retval, *valid_eku); 2077 return retval; 2078 } 2079 2080 krb5_error_code 2081 pkinit_octetstring2key(krb5_context context, 2082 krb5_enctype etype, 2083 unsigned char *key, 2084 unsigned int dh_key_len, 2085 krb5_keyblock * key_block) 2086 { 2087 krb5_error_code retval; 2088 unsigned char *buf = NULL; 2089 unsigned char md[SHA_DIGEST_LENGTH]; 2090 unsigned char counter; 2091 size_t keybytes, keylength, offset; 2092 krb5_data random_data; 2093 2094 2095 if ((buf = (unsigned char *) malloc(dh_key_len)) == NULL) { 2096 retval = ENOMEM; 2097 goto cleanup; 2098 } 2099 (void) memset(buf, 0, dh_key_len); 2100 2101 counter = 0; 2102 offset = 0; 2103 do { 2104 SHA_CTX c; 2105 2106 SHA1_Init(&c); 2107 SHA1_Update(&c, &counter, 1); 2108 SHA1_Update(&c, key, dh_key_len); 2109 SHA1_Final(md, &c); 2110 2111 if (dh_key_len - offset < sizeof(md)) 2112 (void) memcpy(buf + offset, md, dh_key_len - offset); 2113 else 2114 (void) memcpy(buf + offset, md, sizeof(md)); 2115 2116 offset += sizeof(md); 2117 counter++; 2118 } while (offset < dh_key_len); 2119 2120 /* Solaris Kerberos */ 2121 key_block->magic = KV5M_KEYBLOCK; 2122 key_block->enctype = etype; 2123 2124 retval = krb5_c_keylengths(context, etype, &keybytes, &keylength); 2125 if (retval) 2126 goto cleanup; 2127 2128 key_block->length = keylength; 2129 key_block->contents = calloc(keylength, sizeof(unsigned char *)); 2130 if (key_block->contents == NULL) { 2131 retval = ENOMEM; 2132 goto cleanup; 2133 } 2134 2135 random_data.length = keybytes; 2136 random_data.data = (char *)buf; 2137 2138 retval = krb5_c_random_to_key(context, etype, &random_data, key_block); 2139 2140 cleanup: 2141 if (buf != NULL) 2142 free(buf); 2143 if (retval && key_block->contents != NULL && key_block->length != 0) { 2144 (void) memset(key_block->contents, 0, key_block->length); 2145 key_block->length = 0; 2146 } 2147 2148 return retval; 2149 } 2150 2151 /* ARGSUSED */ 2152 krb5_error_code 2153 client_create_dh(krb5_context context, 2154 pkinit_plg_crypto_context plg_cryptoctx, 2155 pkinit_req_crypto_context cryptoctx, 2156 pkinit_identity_crypto_context id_cryptoctx, 2157 int dh_size, 2158 unsigned char **dh_params, 2159 unsigned int *dh_params_len, 2160 unsigned char **dh_pubkey, 2161 unsigned int *dh_pubkey_len) 2162 { 2163 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; 2164 unsigned char *buf = NULL; 2165 int dh_err = 0; 2166 ASN1_INTEGER *pub_key = NULL; 2167 2168 if (cryptoctx->dh == NULL) { 2169 if ((cryptoctx->dh = DH_new()) == NULL) 2170 goto cleanup; 2171 if ((cryptoctx->dh->g = BN_new()) == NULL || 2172 (cryptoctx->dh->q = BN_new()) == NULL) 2173 goto cleanup; 2174 2175 switch(dh_size) { 2176 case 1024: 2177 pkiDebug("client uses 1024 DH keys\n"); 2178 cryptoctx->dh->p = get_rfc2409_prime_1024(NULL); 2179 break; 2180 case 2048: 2181 pkiDebug("client uses 2048 DH keys\n"); 2182 cryptoctx->dh->p = BN_bin2bn(pkinit_2048_dhprime, 2183 sizeof(pkinit_2048_dhprime), NULL); 2184 break; 2185 case 4096: 2186 pkiDebug("client uses 4096 DH keys\n"); 2187 cryptoctx->dh->p = BN_bin2bn(pkinit_4096_dhprime, 2188 sizeof(pkinit_4096_dhprime), NULL); 2189 break; 2190 default: 2191 goto cleanup; 2192 } 2193 2194 BN_set_word((cryptoctx->dh->g), DH_GENERATOR_2); 2195 BN_rshift1(cryptoctx->dh->q, cryptoctx->dh->p); 2196 } 2197 2198 DH_generate_key(cryptoctx->dh); 2199 /* Solaris Kerberos */ 2200 #ifdef DEBUG 2201 DH_check(cryptoctx->dh, &dh_err); 2202 if (dh_err != 0) { 2203 pkiDebug("Warning: dh_check failed with %d\n", dh_err); 2204 if (dh_err & DH_CHECK_P_NOT_PRIME) 2205 pkiDebug("p value is not prime\n"); 2206 if (dh_err & DH_CHECK_P_NOT_SAFE_PRIME) 2207 pkiDebug("p value is not a safe prime\n"); 2208 if (dh_err & DH_UNABLE_TO_CHECK_GENERATOR) 2209 pkiDebug("unable to check the generator value\n"); 2210 if (dh_err & DH_NOT_SUITABLE_GENERATOR) 2211 pkiDebug("the g value is not a generator\n"); 2212 } 2213 #endif 2214 #ifdef DEBUG_DH 2215 print_dh(cryptoctx->dh, "client's DH params\n"); 2216 print_pubkey(cryptoctx->dh->pub_key, "client's pub_key="); 2217 #endif 2218 2219 DH_check_pub_key(cryptoctx->dh, cryptoctx->dh->pub_key, &dh_err); 2220 if (dh_err != 0) { 2221 pkiDebug("dh_check_pub_key failed with %d\n", dh_err); 2222 goto cleanup; 2223 } 2224 2225 /* pack DHparams */ 2226 /* aglo: usually we could just call i2d_DHparams to encode DH params 2227 * however, PKINIT requires RFC3279 encoding and openssl does pkcs#3. 2228 */ 2229 retval = pkinit_encode_dh_params(cryptoctx->dh->p, cryptoctx->dh->g, 2230 cryptoctx->dh->q, dh_params, dh_params_len); 2231 if (retval) 2232 goto cleanup; 2233 2234 /* pack DH public key */ 2235 /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this 2236 * encoding shall be used as the contents (the value) of the 2237 * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo 2238 * data element 2239 */ 2240 if ((pub_key = BN_to_ASN1_INTEGER(cryptoctx->dh->pub_key, NULL)) == NULL) 2241 goto cleanup; 2242 *dh_pubkey_len = i2d_ASN1_INTEGER(pub_key, NULL); 2243 if ((buf = *dh_pubkey = (unsigned char *) 2244 malloc((size_t) *dh_pubkey_len)) == NULL) { 2245 retval = ENOMEM; 2246 goto cleanup; 2247 } 2248 i2d_ASN1_INTEGER(pub_key, &buf); 2249 2250 if (pub_key != NULL) 2251 ASN1_INTEGER_free(pub_key); 2252 2253 retval = 0; 2254 return retval; 2255 2256 cleanup: 2257 if (cryptoctx->dh != NULL) 2258 DH_free(cryptoctx->dh); 2259 cryptoctx->dh = NULL; 2260 if (*dh_params != NULL) 2261 free(*dh_params); 2262 *dh_params = NULL; 2263 if (*dh_pubkey != NULL) 2264 free(*dh_pubkey); 2265 *dh_pubkey = NULL; 2266 if (pub_key != NULL) 2267 ASN1_INTEGER_free(pub_key); 2268 2269 return retval; 2270 } 2271 2272 /* ARGSUSED */ 2273 krb5_error_code 2274 client_process_dh(krb5_context context, 2275 pkinit_plg_crypto_context plg_cryptoctx, 2276 pkinit_req_crypto_context cryptoctx, 2277 pkinit_identity_crypto_context id_cryptoctx, 2278 unsigned char *subjectPublicKey_data, 2279 unsigned int subjectPublicKey_length, 2280 unsigned char **client_key, 2281 unsigned int *client_key_len) 2282 { 2283 /* Solaris Kerberos */ 2284 krb5_error_code retval = KRB5_PREAUTH_FAILED; 2285 BIGNUM *server_pub_key = NULL; 2286 ASN1_INTEGER *pub_key = NULL; 2287 const unsigned char *p = NULL; 2288 unsigned char *data = NULL; 2289 long data_len; 2290 2291 /* decode subjectPublicKey (retrieve INTEGER from OCTET_STRING) */ 2292 2293 if (der_decode_data(subjectPublicKey_data, (long)subjectPublicKey_length, 2294 &data, &data_len) != 0) { 2295 pkiDebug("failed to decode subjectPublicKey\n"); 2296 /* Solaris Kerberos */ 2297 retval = KRB5_PREAUTH_FAILED; 2298 goto cleanup; 2299 } 2300 2301 *client_key_len = DH_size(cryptoctx->dh); 2302 if ((*client_key = (unsigned char *) 2303 malloc((size_t) *client_key_len)) == NULL) { 2304 retval = ENOMEM; 2305 goto cleanup; 2306 } 2307 p = data; 2308 if ((pub_key = d2i_ASN1_INTEGER(NULL, &p, data_len)) == NULL) 2309 goto cleanup; 2310 if ((server_pub_key = ASN1_INTEGER_to_BN(pub_key, NULL)) == NULL) 2311 goto cleanup; 2312 2313 DH_compute_key(*client_key, server_pub_key, cryptoctx->dh); 2314 #ifdef DEBUG_DH 2315 print_pubkey(server_pub_key, "server's pub_key="); 2316 pkiDebug("client secret key (%d)= ", *client_key_len); 2317 print_buffer(*client_key, *client_key_len); 2318 #endif 2319 2320 retval = 0; 2321 if (server_pub_key != NULL) 2322 BN_free(server_pub_key); 2323 if (pub_key != NULL) 2324 ASN1_INTEGER_free(pub_key); 2325 if (data != NULL) 2326 free (data); 2327 2328 return retval; 2329 2330 cleanup: 2331 if (*client_key != NULL) 2332 free(*client_key); 2333 *client_key = NULL; 2334 if (pub_key != NULL) 2335 ASN1_INTEGER_free(pub_key); 2336 if (data != NULL) 2337 free (data); 2338 2339 return retval; 2340 } 2341 2342 /* ARGSUSED */ 2343 krb5_error_code 2344 server_check_dh(krb5_context context, 2345 pkinit_plg_crypto_context cryptoctx, 2346 pkinit_req_crypto_context req_cryptoctx, 2347 pkinit_identity_crypto_context id_cryptoctx, 2348 krb5_octet_data *dh_params, 2349 int minbits) 2350 { 2351 DH *dh = NULL; 2352 unsigned char *tmp = NULL; 2353 int dh_prime_bits; 2354 krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; 2355 2356 tmp = dh_params->data; 2357 dh = DH_new(); 2358 dh = pkinit_decode_dh_params(&dh, &tmp, dh_params->length); 2359 if (dh == NULL) { 2360 pkiDebug("failed to decode dhparams\n"); 2361 goto cleanup; 2362 } 2363 2364 /* KDC SHOULD check to see if the key parameters satisfy its policy */ 2365 dh_prime_bits = BN_num_bits(dh->p); 2366 if (minbits && dh_prime_bits < minbits) { 2367 pkiDebug("client sent dh params with %d bits, we require %d\n", 2368 dh_prime_bits, minbits); 2369 goto cleanup; 2370 } 2371 2372 /* check dhparams is group 2 */ 2373 if (pkinit_check_dh_params(cryptoctx->dh_1024->p, 2374 dh->p, dh->g, dh->q) == 0) { 2375 retval = 0; 2376 goto cleanup; 2377 } 2378 2379 /* check dhparams is group 14 */ 2380 if (pkinit_check_dh_params(cryptoctx->dh_2048->p, 2381 dh->p, dh->g, dh->q) == 0) { 2382 retval = 0; 2383 goto cleanup; 2384 } 2385 2386 /* check dhparams is group 16 */ 2387 if (pkinit_check_dh_params(cryptoctx->dh_4096->p, 2388 dh->p, dh->g, dh->q) == 0) { 2389 retval = 0; 2390 goto cleanup; 2391 } 2392 2393 cleanup: 2394 if (retval == 0) 2395 req_cryptoctx->dh = dh; 2396 else 2397 DH_free(dh); 2398 2399 return retval; 2400 } 2401 2402 /* kdc's dh function */ 2403 /* ARGSUSED */ 2404 krb5_error_code 2405 server_process_dh(krb5_context context, 2406 pkinit_plg_crypto_context plg_cryptoctx, 2407 pkinit_req_crypto_context cryptoctx, 2408 pkinit_identity_crypto_context id_cryptoctx, 2409 unsigned char *data, 2410 unsigned int data_len, 2411 unsigned char **dh_pubkey, 2412 unsigned int *dh_pubkey_len, 2413 unsigned char **server_key, 2414 unsigned int *server_key_len) 2415 { 2416 /* Solaris Kerberos */ 2417 krb5_error_code retval = KRB5KRB_ERR_GENERIC; 2418 DH *dh = NULL, *dh_server = NULL; 2419 unsigned char *p = NULL; 2420 ASN1_INTEGER *pub_key = NULL; 2421 2422 /* get client's received DH parameters that we saved in server_check_dh */ 2423 dh = cryptoctx->dh; 2424 2425 dh_server = DH_new(); 2426 if (dh_server == NULL) 2427 goto cleanup; 2428 dh_server->p = BN_dup(dh->p); 2429 dh_server->g = BN_dup(dh->g); 2430 dh_server->q = BN_dup(dh->q); 2431 2432 /* decode client's public key */ 2433 p = data; 2434 pub_key = d2i_ASN1_INTEGER(NULL, (const unsigned char **)&p, (int)data_len); 2435 if (pub_key == NULL) 2436 goto cleanup; 2437 dh->pub_key = ASN1_INTEGER_to_BN(pub_key, NULL); 2438 if (dh->pub_key == NULL) 2439 goto cleanup; 2440 ASN1_INTEGER_free(pub_key); 2441 2442 if (!DH_generate_key(dh_server)) 2443 goto cleanup; 2444 2445 /* generate DH session key */ 2446 *server_key_len = DH_size(dh_server); 2447 if ((*server_key = (unsigned char *) malloc((size_t)*server_key_len)) == NULL) 2448 goto cleanup; 2449 DH_compute_key(*server_key, dh->pub_key, dh_server); 2450 2451 #ifdef DEBUG_DH 2452 print_dh(dh_server, "client&server's DH params\n"); 2453 print_pubkey(dh->pub_key, "client's pub_key="); 2454 print_pubkey(dh_server->pub_key, "server's pub_key="); 2455 pkiDebug("server secret key="); 2456 print_buffer(*server_key, *server_key_len); 2457 #endif 2458 2459 /* KDC reply */ 2460 /* pack DH public key */ 2461 /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this 2462 * encoding shall be used as the contents (the value) of the 2463 * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo 2464 * data element 2465 */ 2466 if ((pub_key = BN_to_ASN1_INTEGER(dh_server->pub_key, NULL)) == NULL) 2467 goto cleanup; 2468 *dh_pubkey_len = i2d_ASN1_INTEGER(pub_key, NULL); 2469 if ((p = *dh_pubkey = (unsigned char *) malloc((size_t)*dh_pubkey_len)) == NULL) 2470 goto cleanup; 2471 i2d_ASN1_INTEGER(pub_key, &p); 2472 if (pub_key != NULL) 2473 ASN1_INTEGER_free(pub_key); 2474 2475 retval = 0; 2476 2477 if (dh_server != NULL) 2478 DH_free(dh_server); 2479 return retval; 2480 2481 cleanup: 2482 if (dh_server != NULL) 2483 DH_free(dh_server); 2484 if (*dh_pubkey != NULL) 2485 free(*dh_pubkey); 2486 if (*server_key != NULL) 2487 free(*server_key); 2488 2489 return retval; 2490 } 2491 2492 /* 2493 * Solaris Kerberos: 2494 * Add locking around did_init to make it MT-safe. 2495 */ 2496 static krb5_error_code 2497 openssl_init() 2498 { 2499 krb5_error_code ret = 0; 2500 static int did_init = 0; 2501 static k5_mutex_t init_mutex = K5_MUTEX_PARTIAL_INITIALIZER; 2502 2503 ret = k5_mutex_lock(&init_mutex); 2504 if (ret == 0) { 2505 if (!did_init) { 2506 /* initialize openssl routines */ 2507 CRYPTO_malloc_init(); 2508 ERR_load_crypto_strings(); 2509 OpenSSL_add_all_algorithms(); 2510 did_init++; 2511 } 2512 k5_mutex_unlock(&init_mutex); 2513 } 2514 return (ret); 2515 } 2516 2517 static krb5_error_code 2518 pkinit_encode_dh_params(BIGNUM *p, BIGNUM *g, BIGNUM *q, 2519 unsigned char **buf, unsigned int *buf_len) 2520 { 2521 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; 2522 int bufsize = 0, r = 0; 2523 unsigned char *tmp = NULL; 2524 ASN1_INTEGER *ap = NULL, *ag = NULL, *aq = NULL; 2525 2526 if ((ap = BN_to_ASN1_INTEGER(p, NULL)) == NULL) 2527 goto cleanup; 2528 if ((ag = BN_to_ASN1_INTEGER(g, NULL)) == NULL) 2529 goto cleanup; 2530 if ((aq = BN_to_ASN1_INTEGER(q, NULL)) == NULL) 2531 goto cleanup; 2532 bufsize = i2d_ASN1_INTEGER(ap, NULL); 2533 bufsize += i2d_ASN1_INTEGER(ag, NULL); 2534 bufsize += i2d_ASN1_INTEGER(aq, NULL); 2535 2536 r = ASN1_object_size(1, bufsize, V_ASN1_SEQUENCE); 2537 2538 tmp = *buf = (unsigned char *)malloc((size_t) r); 2539 if (tmp == NULL) 2540 goto cleanup; 2541 2542 ASN1_put_object(&tmp, 1, bufsize, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); 2543 2544 i2d_ASN1_INTEGER(ap, &tmp); 2545 i2d_ASN1_INTEGER(ag, &tmp); 2546 i2d_ASN1_INTEGER(aq, &tmp); 2547 2548 *buf_len = r; 2549 2550 retval = 0; 2551 2552 cleanup: 2553 if (ap != NULL) 2554 ASN1_INTEGER_free(ap); 2555 if (ag != NULL) 2556 ASN1_INTEGER_free(ag); 2557 if (aq != NULL) 2558 ASN1_INTEGER_free(aq); 2559 2560 return retval; 2561 } 2562 2563 static DH * 2564 pkinit_decode_dh_params(DH ** a, unsigned char **pp, unsigned int len) 2565 { 2566 ASN1_INTEGER ai, *aip = NULL; 2567 long length = (long) len; 2568 2569 M_ASN1_D2I_vars(a, DH *, DH_new); 2570 2571 M_ASN1_D2I_Init(); 2572 M_ASN1_D2I_start_sequence(); 2573 aip = &ai; 2574 ai.data = NULL; 2575 ai.length = 0; 2576 M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER); 2577 if (aip == NULL) 2578 return NULL; 2579 else { 2580 (*a)->p = ASN1_INTEGER_to_BN(aip, NULL); 2581 if ((*a)->p == NULL) 2582 return NULL; 2583 if (ai.data != NULL) { 2584 OPENSSL_free(ai.data); 2585 ai.data = NULL; 2586 ai.length = 0; 2587 } 2588 } 2589 M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER); 2590 if (aip == NULL) 2591 return NULL; 2592 else { 2593 (*a)->g = ASN1_INTEGER_to_BN(aip, NULL); 2594 if ((*a)->g == NULL) 2595 return NULL; 2596 if (ai.data != NULL) { 2597 OPENSSL_free(ai.data); 2598 ai.data = NULL; 2599 ai.length = 0; 2600 } 2601 2602 } 2603 M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER); 2604 if (aip == NULL) 2605 return NULL; 2606 else { 2607 (*a)->q = ASN1_INTEGER_to_BN(aip, NULL); 2608 if ((*a)->q == NULL) 2609 return NULL; 2610 if (ai.data != NULL) { 2611 OPENSSL_free(ai.data); 2612 ai.data = NULL; 2613 ai.length = 0; 2614 } 2615 2616 } 2617 M_ASN1_D2I_end_sequence(); 2618 M_ASN1_D2I_Finish(a, DH_free, 0); 2619 2620 } 2621 2622 static krb5_error_code 2623 pkinit_create_sequence_of_principal_identifiers( 2624 krb5_context context, 2625 pkinit_plg_crypto_context plg_cryptoctx, 2626 pkinit_req_crypto_context req_cryptoctx, 2627 pkinit_identity_crypto_context id_cryptoctx, 2628 int type, 2629 krb5_data **out_data) 2630 { 2631 krb5_error_code retval = KRB5KRB_ERR_GENERIC; 2632 krb5_external_principal_identifier **krb5_trusted_certifiers = NULL; 2633 krb5_data *td_certifiers = NULL, *data = NULL; 2634 krb5_typed_data **typed_data = NULL; 2635 2636 switch(type) { 2637 case TD_TRUSTED_CERTIFIERS: 2638 retval = create_krb5_trustedCertifiers(context, plg_cryptoctx, 2639 req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers); 2640 if (retval) { 2641 pkiDebug("create_krb5_trustedCertifiers failed\n"); 2642 goto cleanup; 2643 } 2644 break; 2645 case TD_INVALID_CERTIFICATES: 2646 retval = create_krb5_invalidCertificates(context, plg_cryptoctx, 2647 req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers); 2648 if (retval) { 2649 pkiDebug("create_krb5_invalidCertificates failed\n"); 2650 goto cleanup; 2651 } 2652 break; 2653 default: 2654 retval = -1; 2655 goto cleanup; 2656 } 2657 2658 retval = k5int_encode_krb5_td_trusted_certifiers((const krb5_external_principal_identifier **)krb5_trusted_certifiers, &td_certifiers); 2659 if (retval) { 2660 pkiDebug("encode_krb5_td_trusted_certifiers failed\n"); 2661 goto cleanup; 2662 } 2663 #ifdef DEBUG_ASN1 2664 print_buffer_bin((unsigned char *)td_certifiers->data, 2665 td_certifiers->length, "/tmp/kdc_td_certifiers"); 2666 #endif 2667 typed_data = malloc (2 * sizeof(krb5_typed_data *)); 2668 if (typed_data == NULL) { 2669 retval = ENOMEM; 2670 goto cleanup; 2671 } 2672 typed_data[1] = NULL; 2673 init_krb5_typed_data(&typed_data[0]); 2674 if (typed_data[0] == NULL) { 2675 retval = ENOMEM; 2676 goto cleanup; 2677 } 2678 typed_data[0]->type = type; 2679 typed_data[0]->length = td_certifiers->length; 2680 typed_data[0]->data = (unsigned char *)td_certifiers->data; 2681 retval = k5int_encode_krb5_typed_data((const krb5_typed_data **)typed_data, 2682 &data); 2683 if (retval) { 2684 pkiDebug("encode_krb5_typed_data failed\n"); 2685 goto cleanup; 2686 } 2687 #ifdef DEBUG_ASN1 2688 print_buffer_bin((unsigned char *)data->data, data->length, 2689 "/tmp/kdc_edata"); 2690 #endif 2691 *out_data = (krb5_data *)malloc(sizeof(krb5_data)); 2692 (*out_data)->length = data->length; 2693 (*out_data)->data = (char *)malloc(data->length); 2694 (void) memcpy((*out_data)->data, data->data, data->length); 2695 2696 retval = 0; 2697 2698 cleanup: 2699 if (krb5_trusted_certifiers != NULL) 2700 free_krb5_external_principal_identifier(&krb5_trusted_certifiers); 2701 2702 if (data != NULL) { 2703 if (data->data != NULL) 2704 free(data->data); 2705 free(data); 2706 } 2707 2708 if (td_certifiers != NULL) 2709 free(td_certifiers); 2710 2711 if (typed_data != NULL) 2712 free_krb5_typed_data(&typed_data); 2713 2714 return retval; 2715 } 2716 2717 krb5_error_code 2718 pkinit_create_td_trusted_certifiers(krb5_context context, 2719 pkinit_plg_crypto_context plg_cryptoctx, 2720 pkinit_req_crypto_context req_cryptoctx, 2721 pkinit_identity_crypto_context id_cryptoctx, 2722 krb5_data **out_data) 2723 { 2724 krb5_error_code retval = KRB5KRB_ERR_GENERIC; 2725 2726 retval = pkinit_create_sequence_of_principal_identifiers(context, 2727 plg_cryptoctx, req_cryptoctx, id_cryptoctx, 2728 TD_TRUSTED_CERTIFIERS, out_data); 2729 2730 return retval; 2731 } 2732 2733 krb5_error_code 2734 pkinit_create_td_invalid_certificate( 2735 krb5_context context, 2736 pkinit_plg_crypto_context plg_cryptoctx, 2737 pkinit_req_crypto_context req_cryptoctx, 2738 pkinit_identity_crypto_context id_cryptoctx, 2739 krb5_data **out_data) 2740 { 2741 krb5_error_code retval = KRB5KRB_ERR_GENERIC; 2742 2743 retval = pkinit_create_sequence_of_principal_identifiers(context, 2744 plg_cryptoctx, req_cryptoctx, id_cryptoctx, 2745 TD_INVALID_CERTIFICATES, out_data); 2746 2747 return retval; 2748 } 2749 2750 /* ARGSUSED */ 2751 krb5_error_code 2752 pkinit_create_td_dh_parameters(krb5_context context, 2753 pkinit_plg_crypto_context plg_cryptoctx, 2754 pkinit_req_crypto_context req_cryptoctx, 2755 pkinit_identity_crypto_context id_cryptoctx, 2756 pkinit_plg_opts *opts, 2757 krb5_data **out_data) 2758 { 2759 /* Solaris Kerberos */ 2760 krb5_error_code retval = KRB5KRB_ERR_GENERIC; 2761 unsigned int buf1_len = 0, buf2_len = 0, buf3_len = 0, i = 0; 2762 unsigned char *buf1 = NULL, *buf2 = NULL, *buf3 = NULL; 2763 krb5_typed_data **typed_data = NULL; 2764 krb5_data *data = NULL, *encoded_algId = NULL; 2765 krb5_algorithm_identifier **algId = NULL; 2766 2767 /* Solaris Kerberos */ 2768 if (opts->dh_min_bits > 4096) { 2769 retval = EINVAL; 2770 goto cleanup; 2771 } 2772 2773 if (opts->dh_min_bits <= 1024) { 2774 retval = pkinit_encode_dh_params(plg_cryptoctx->dh_1024->p, 2775 plg_cryptoctx->dh_1024->g, plg_cryptoctx->dh_1024->q, 2776 &buf1, &buf1_len); 2777 if (retval) 2778 goto cleanup; 2779 } 2780 if (opts->dh_min_bits <= 2048) { 2781 retval = pkinit_encode_dh_params(plg_cryptoctx->dh_2048->p, 2782 plg_cryptoctx->dh_2048->g, plg_cryptoctx->dh_2048->q, 2783 &buf2, &buf2_len); 2784 if (retval) 2785 goto cleanup; 2786 } 2787 retval = pkinit_encode_dh_params(plg_cryptoctx->dh_4096->p, 2788 plg_cryptoctx->dh_4096->g, plg_cryptoctx->dh_4096->q, 2789 &buf3, &buf3_len); 2790 if (retval) 2791 goto cleanup; 2792 2793 if (opts->dh_min_bits <= 1024) { 2794 algId = malloc(4 * sizeof(krb5_algorithm_identifier *)); 2795 if (algId == NULL) 2796 goto cleanup; 2797 algId[3] = NULL; 2798 algId[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier)); 2799 if (algId[0] == NULL) 2800 goto cleanup; 2801 algId[0]->parameters.data = (unsigned char *)malloc(buf2_len); 2802 if (algId[0]->parameters.data == NULL) 2803 goto cleanup; 2804 (void) memcpy(algId[0]->parameters.data, buf2, buf2_len); 2805 algId[0]->parameters.length = buf2_len; 2806 algId[0]->algorithm = dh_oid; 2807 2808 algId[1] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier)); 2809 if (algId[1] == NULL) 2810 goto cleanup; 2811 algId[1]->parameters.data = (unsigned char *)malloc(buf3_len); 2812 if (algId[1]->parameters.data == NULL) 2813 goto cleanup; 2814 (void) memcpy(algId[1]->parameters.data, buf3, buf3_len); 2815 algId[1]->parameters.length = buf3_len; 2816 algId[1]->algorithm = dh_oid; 2817 2818 algId[2] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier)); 2819 if (algId[2] == NULL) 2820 goto cleanup; 2821 algId[2]->parameters.data = (unsigned char *)malloc(buf1_len); 2822 if (algId[2]->parameters.data == NULL) 2823 goto cleanup; 2824 (void) memcpy(algId[2]->parameters.data, buf1, buf1_len); 2825 algId[2]->parameters.length = buf1_len; 2826 algId[2]->algorithm = dh_oid; 2827 2828 } else if (opts->dh_min_bits <= 2048) { 2829 algId = malloc(3 * sizeof(krb5_algorithm_identifier *)); 2830 if (algId == NULL) 2831 goto cleanup; 2832 algId[2] = NULL; 2833 algId[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier)); 2834 if (algId[0] == NULL) 2835 goto cleanup; 2836 algId[0]->parameters.data = (unsigned char *)malloc(buf2_len); 2837 if (algId[0]->parameters.data == NULL) 2838 goto cleanup; 2839 (void) memcpy(algId[0]->parameters.data, buf2, buf2_len); 2840 algId[0]->parameters.length = buf2_len; 2841 algId[0]->algorithm = dh_oid; 2842 2843 algId[1] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier)); 2844 if (algId[1] == NULL) 2845 goto cleanup; 2846 algId[1]->parameters.data = (unsigned char *)malloc(buf3_len); 2847 if (algId[1]->parameters.data == NULL) 2848 goto cleanup; 2849 (void) memcpy(algId[1]->parameters.data, buf3, buf3_len); 2850 algId[1]->parameters.length = buf3_len; 2851 algId[1]->algorithm = dh_oid; 2852 2853 } else if (opts->dh_min_bits <= 4096) { 2854 algId = malloc(2 * sizeof(krb5_algorithm_identifier *)); 2855 if (algId == NULL) 2856 goto cleanup; 2857 algId[1] = NULL; 2858 algId[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier)); 2859 if (algId[0] == NULL) 2860 goto cleanup; 2861 algId[0]->parameters.data = (unsigned char *)malloc(buf3_len); 2862 if (algId[0]->parameters.data == NULL) 2863 goto cleanup; 2864 (void) memcpy(algId[0]->parameters.data, buf3, buf3_len); 2865 algId[0]->parameters.length = buf3_len; 2866 algId[0]->algorithm = dh_oid; 2867 2868 } 2869 retval = k5int_encode_krb5_td_dh_parameters((const krb5_algorithm_identifier **)algId, &encoded_algId); 2870 if (retval) 2871 goto cleanup; 2872 #ifdef DEBUG_ASN1 2873 print_buffer_bin((unsigned char *)encoded_algId->data, 2874 encoded_algId->length, "/tmp/kdc_td_dh_params"); 2875 #endif 2876 typed_data = malloc (2 * sizeof(krb5_typed_data *)); 2877 if (typed_data == NULL) { 2878 retval = ENOMEM; 2879 goto cleanup; 2880 } 2881 typed_data[1] = NULL; 2882 init_krb5_typed_data(&typed_data[0]); 2883 if (typed_data == NULL) { 2884 retval = ENOMEM; 2885 goto cleanup; 2886 } 2887 typed_data[0]->type = TD_DH_PARAMETERS; 2888 typed_data[0]->length = encoded_algId->length; 2889 typed_data[0]->data = (unsigned char *)encoded_algId->data; 2890 retval = k5int_encode_krb5_typed_data((const krb5_typed_data**)typed_data, 2891 &data); 2892 if (retval) { 2893 pkiDebug("encode_krb5_typed_data failed\n"); 2894 goto cleanup; 2895 } 2896 #ifdef DEBUG_ASN1 2897 print_buffer_bin((unsigned char *)data->data, data->length, 2898 "/tmp/kdc_edata"); 2899 #endif 2900 *out_data = (krb5_data *)malloc(sizeof(krb5_data)); 2901 if (*out_data == NULL) 2902 goto cleanup; 2903 (*out_data)->length = data->length; 2904 (*out_data)->data = (char *)malloc(data->length); 2905 if ((*out_data)->data == NULL) { 2906 free(*out_data); 2907 *out_data = NULL; 2908 goto cleanup; 2909 } 2910 (void) memcpy((*out_data)->data, data->data, data->length); 2911 2912 retval = 0; 2913 cleanup: 2914 2915 if (buf1 != NULL) 2916 free(buf1); 2917 if (buf2 != NULL) 2918 free(buf2); 2919 if (buf3 != NULL) 2920 free(buf3); 2921 if (data != NULL) { 2922 if (data->data != NULL) 2923 free(data->data); 2924 free(data); 2925 } 2926 if (typed_data != NULL) 2927 free_krb5_typed_data(&typed_data); 2928 if (encoded_algId != NULL) 2929 free(encoded_algId); 2930 2931 if (algId != NULL) { 2932 while(algId[i] != NULL) { 2933 if (algId[i]->parameters.data != NULL) 2934 free(algId[i]->parameters.data); 2935 free(algId[i]); 2936 i++; 2937 } 2938 free(algId); 2939 } 2940 2941 return retval; 2942 } 2943 2944 /* ARGSUSED */ 2945 krb5_error_code 2946 pkinit_check_kdc_pkid(krb5_context context, 2947 pkinit_plg_crypto_context plg_cryptoctx, 2948 pkinit_req_crypto_context req_cryptoctx, 2949 pkinit_identity_crypto_context id_cryptoctx, 2950 unsigned char *pdid_buf, 2951 unsigned int pkid_len, 2952 int *valid_kdcPkId) 2953 { 2954 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; 2955 PKCS7_ISSUER_AND_SERIAL *is = NULL; 2956 const unsigned char *p = pdid_buf; 2957 int status = 1; 2958 X509 *kdc_cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index); 2959 2960 *valid_kdcPkId = 0; 2961 pkiDebug("found kdcPkId in AS REQ\n"); 2962 is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p, (int)pkid_len); 2963 if (is == NULL) 2964 goto cleanup; 2965 2966 status = X509_NAME_cmp(X509_get_issuer_name(kdc_cert), is->issuer); 2967 if (!status) { 2968 status = ASN1_INTEGER_cmp(X509_get_serialNumber(kdc_cert), is->serial); 2969 if (!status) 2970 *valid_kdcPkId = 1; 2971 } 2972 2973 retval = 0; 2974 cleanup: 2975 X509_NAME_free(is->issuer); 2976 ASN1_INTEGER_free(is->serial); 2977 free(is); 2978 2979 return retval; 2980 } 2981 2982 static int 2983 pkinit_check_dh_params(BIGNUM * p1, BIGNUM * p2, BIGNUM * g1, BIGNUM * q1) 2984 { 2985 BIGNUM *g2 = NULL, *q2 = NULL; 2986 /* Solaris Kerberos */ 2987 int retval = EINVAL; 2988 2989 if (!BN_cmp(p1, p2)) { 2990 g2 = BN_new(); 2991 BN_set_word(g2, DH_GENERATOR_2); 2992 if (!BN_cmp(g1, g2)) { 2993 q2 = BN_new(); 2994 BN_rshift1(q2, p1); 2995 if (!BN_cmp(q1, q2)) { 2996 pkiDebug("good %d dhparams\n", BN_num_bits(p1)); 2997 retval = 0; 2998 } else 2999 pkiDebug("bad group 2 q dhparameter\n"); 3000 BN_free(q2); 3001 } else 3002 pkiDebug("bad g dhparameter\n"); 3003 BN_free(g2); 3004 } else 3005 pkiDebug("p is not well-known group 2 dhparameter\n"); 3006 3007 return retval; 3008 } 3009 3010 /* ARGSUSED */ 3011 krb5_error_code 3012 pkinit_process_td_dh_params(krb5_context context, 3013 pkinit_plg_crypto_context cryptoctx, 3014 pkinit_req_crypto_context req_cryptoctx, 3015 pkinit_identity_crypto_context id_cryptoctx, 3016 krb5_algorithm_identifier **algId, 3017 int *new_dh_size) 3018 { 3019 krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; 3020 int i = 0, use_sent_dh = 0, ok = 0; 3021 3022 pkiDebug("dh parameters\n"); 3023 3024 while (algId[i] != NULL) { 3025 DH *dh = NULL; 3026 unsigned char *tmp = NULL; 3027 int dh_prime_bits = 0; 3028 3029 if (algId[i]->algorithm.length != dh_oid.length || 3030 memcmp(algId[i]->algorithm.data, dh_oid.data, dh_oid.length)) 3031 goto cleanup; 3032 3033 tmp = algId[i]->parameters.data; 3034 dh = DH_new(); 3035 dh = pkinit_decode_dh_params(&dh, &tmp, algId[i]->parameters.length); 3036 dh_prime_bits = BN_num_bits(dh->p); 3037 pkiDebug("client sent %d DH bits server prefers %d DH bits\n", 3038 *new_dh_size, dh_prime_bits); 3039 switch(dh_prime_bits) { 3040 case 1024: 3041 if (pkinit_check_dh_params(cryptoctx->dh_1024->p, dh->p, 3042 dh->g, dh->q) == 0) { 3043 *new_dh_size = 1024; 3044 ok = 1; 3045 } 3046 break; 3047 case 2048: 3048 if (pkinit_check_dh_params(cryptoctx->dh_2048->p, dh->p, 3049 dh->g, dh->q) == 0) { 3050 *new_dh_size = 2048; 3051 ok = 1; 3052 } 3053 break; 3054 case 4096: 3055 if (pkinit_check_dh_params(cryptoctx->dh_4096->p, dh->p, 3056 dh->g, dh->q) == 0) { 3057 *new_dh_size = 4096; 3058 ok = 1; 3059 } 3060 break; 3061 default: 3062 break; 3063 } 3064 if (!ok) { 3065 DH_check(dh, &retval); 3066 if (retval != 0) { 3067 pkiDebug("DH parameters provided by server are unacceptable\n"); 3068 retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; 3069 } 3070 else { 3071 use_sent_dh = 1; 3072 ok = 1; 3073 } 3074 } 3075 if (!use_sent_dh) 3076 DH_free(dh); 3077 if (ok) { 3078 if (req_cryptoctx->dh != NULL) { 3079 DH_free(req_cryptoctx->dh); 3080 req_cryptoctx->dh = NULL; 3081 } 3082 if (use_sent_dh) 3083 req_cryptoctx->dh = dh; 3084 break; 3085 } 3086 i++; 3087 } 3088 3089 if (ok) 3090 retval = 0; 3091 3092 cleanup: 3093 return retval; 3094 } 3095 3096 /* ARGSUSED */ 3097 static int 3098 openssl_callback(int ok, X509_STORE_CTX * ctx) 3099 { 3100 #ifdef DEBUG 3101 if (!ok) { 3102 char buf[DN_BUF_LEN]; 3103 3104 X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), buf, sizeof(buf)); 3105 pkiDebug("cert = %s\n", buf); 3106 pkiDebug("callback function: %d (%s)\n", ctx->error, 3107 X509_verify_cert_error_string(ctx->error)); 3108 } 3109 #endif 3110 return ok; 3111 } 3112 3113 static int 3114 openssl_callback_ignore_crls(int ok, X509_STORE_CTX * ctx) 3115 { 3116 if (!ok) { 3117 switch (ctx->error) { 3118 case X509_V_ERR_UNABLE_TO_GET_CRL: 3119 return 1; 3120 default: 3121 return 0; 3122 } 3123 } 3124 return ok; 3125 } 3126 3127 static ASN1_OBJECT * 3128 pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx, int pkcs7_type) 3129 { 3130 switch (pkcs7_type) { 3131 case CMS_SIGN_CLIENT: 3132 return cryptoctx->id_pkinit_authData; 3133 case CMS_SIGN_DRAFT9: 3134 return OBJ_nid2obj(NID_pkcs7_data); 3135 case CMS_SIGN_SERVER: 3136 return cryptoctx->id_pkinit_DHKeyData; 3137 case CMS_ENVEL_SERVER: 3138 return cryptoctx->id_pkinit_rkeyData; 3139 default: 3140 return NULL; 3141 } 3142 3143 } 3144 3145 #ifdef LONGHORN_BETA_COMPAT 3146 #if 0 3147 /* 3148 * This is a version that worked with Longhorn Beta 3. 3149 */ 3150 static int 3151 wrap_signeddata(unsigned char *data, unsigned int data_len, 3152 unsigned char **out, unsigned int *out_len, 3153 int is_longhorn_server) 3154 { 3155 3156 unsigned int orig_len = 0, oid_len = 0, tot_len = 0; 3157 ASN1_OBJECT *oid = NULL; 3158 unsigned char *p = NULL; 3159 3160 pkiDebug("%s: This is the Longhorn version and is_longhorn_server = %d\n", 3161 __FUNCTION__, is_longhorn_server); 3162 3163 /* Get length to wrap the original data with SEQUENCE tag */ 3164 tot_len = orig_len = ASN1_object_size(1, (int)data_len, V_ASN1_SEQUENCE); 3165 3166 if (is_longhorn_server == 0) { 3167 /* Add the signedData OID and adjust lengths */ 3168 oid = OBJ_nid2obj(NID_pkcs7_signed); 3169 oid_len = i2d_ASN1_OBJECT(oid, NULL); 3170 3171 tot_len = ASN1_object_size(1, (int)(orig_len+oid_len), V_ASN1_SEQUENCE); 3172 } 3173 3174 p = *out = (unsigned char *)malloc(tot_len); 3175 if (p == NULL) return -1; 3176 3177 if (is_longhorn_server == 0) { 3178 ASN1_put_object(&p, 1, (int)(orig_len+oid_len), 3179 V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); 3180 3181 i2d_ASN1_OBJECT(oid, &p); 3182 3183 ASN1_put_object(&p, 1, (int)data_len, 0, V_ASN1_CONTEXT_SPECIFIC); 3184 } else { 3185 ASN1_put_object(&p, 1, (int)data_len, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); 3186 } 3187 memcpy(p, data, data_len); 3188 3189 *out_len = tot_len; 3190 3191 return 0; 3192 } 3193 #else 3194 /* 3195 * This is a version that works with a patched Longhorn KDC. 3196 * (Which should match SP1 ??). 3197 */ 3198 static int 3199 wrap_signeddata(unsigned char *data, unsigned int data_len, 3200 unsigned char **out, unsigned int *out_len, 3201 int is_longhorn_server) 3202 { 3203 3204 unsigned int oid_len = 0, tot_len = 0, wrap_len = 0, tag_len = 0; 3205 ASN1_OBJECT *oid = NULL; 3206 unsigned char *p = NULL; 3207 3208 pkiDebug("%s: This is the Longhorn version and is_longhorn_server = %d\n", 3209 __FUNCTION__, is_longhorn_server); 3210 3211 /* New longhorn is missing another sequence */ 3212 if (is_longhorn_server == 1) 3213 wrap_len = ASN1_object_size(1, (int)(data_len), V_ASN1_SEQUENCE); 3214 else 3215 wrap_len = data_len; 3216 3217 /* Get length to wrap the original data with SEQUENCE tag */ 3218 tag_len = ASN1_object_size(1, (int)wrap_len, V_ASN1_SEQUENCE); 3219 3220 /* Always add oid */ 3221 oid = OBJ_nid2obj(NID_pkcs7_signed); 3222 oid_len = i2d_ASN1_OBJECT(oid, NULL); 3223 oid_len += tag_len; 3224 3225 tot_len = ASN1_object_size(1, (int)(oid_len), V_ASN1_SEQUENCE); 3226 3227 p = *out = (unsigned char *)malloc(tot_len); 3228 if (p == NULL) 3229 return -1; 3230 3231 ASN1_put_object(&p, 1, (int)(oid_len), 3232 V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); 3233 3234 i2d_ASN1_OBJECT(oid, &p); 3235 3236 ASN1_put_object(&p, 1, (int)wrap_len, 0, V_ASN1_CONTEXT_SPECIFIC); 3237 3238 /* Wrap in extra seq tag */ 3239 if (is_longhorn_server == 1) { 3240 ASN1_put_object(&p, 1, (int)data_len, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); 3241 } 3242 (void) memcpy(p, data, data_len); 3243 3244 *out_len = tot_len; 3245 3246 return 0; 3247 } 3248 3249 #endif 3250 #else 3251 static int 3252 wrap_signeddata(unsigned char *data, unsigned int data_len, 3253 unsigned char **out, unsigned int *out_len) 3254 { 3255 3256 unsigned int orig_len = 0, oid_len = 0, tot_len = 0; 3257 ASN1_OBJECT *oid = NULL; 3258 unsigned char *p = NULL; 3259 3260 /* Get length to wrap the original data with SEQUENCE tag */ 3261 tot_len = orig_len = ASN1_object_size(1, (int)data_len, V_ASN1_SEQUENCE); 3262 3263 /* Add the signedData OID and adjust lengths */ 3264 oid = OBJ_nid2obj(NID_pkcs7_signed); 3265 oid_len = i2d_ASN1_OBJECT(oid, NULL); 3266 3267 tot_len = ASN1_object_size(1, (int)(orig_len+oid_len), V_ASN1_SEQUENCE); 3268 3269 p = *out = (unsigned char *)malloc(tot_len); 3270 if (p == NULL) return -1; 3271 3272 ASN1_put_object(&p, 1, (int)(orig_len+oid_len), 3273 V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); 3274 3275 i2d_ASN1_OBJECT(oid, &p); 3276 3277 ASN1_put_object(&p, 1, (int)data_len, 0, V_ASN1_CONTEXT_SPECIFIC); 3278 (void) memcpy(p, data, data_len); 3279 3280 *out_len = tot_len; 3281 3282 return 0; 3283 } 3284 #endif 3285 3286 static int 3287 prepare_enc_data(unsigned char *indata, 3288 int indata_len, 3289 unsigned char **outdata, 3290 int *outdata_len) 3291 { 3292 /* Solaris Kerberos */ 3293 ASN1_const_CTX c; 3294 long length = indata_len; 3295 int Ttag, Tclass; 3296 long Tlen; 3297 3298 c.pp = (const unsigned char **)&indata; 3299 c.q = *(const unsigned char **)&indata; 3300 c.error = ERR_R_NESTED_ASN1_ERROR; 3301 c.p= *(const unsigned char **)&indata; 3302 c.max = (length == 0)?0:(c.p+length); 3303 3304 asn1_GetSequence(&c,&length); 3305 3306 ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); 3307 c.p += Tlen; 3308 ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); 3309 3310 asn1_const_Finish(&c); 3311 3312 *outdata = (unsigned char *)malloc((size_t)Tlen); 3313 /* Solaris Kerberos */ 3314 if (outdata == NULL) 3315 return ENOMEM; 3316 3317 (void) memcpy(*outdata, c.p, (size_t)Tlen); 3318 *outdata_len = Tlen; 3319 3320 return 0; 3321 } 3322 3323 #ifndef WITHOUT_PKCS11 3324 static void * 3325 pkinit_C_LoadModule(const char *modname, CK_FUNCTION_LIST_PTR_PTR p11p) 3326 { 3327 void *handle; 3328 CK_RV (*getflist)(CK_FUNCTION_LIST_PTR_PTR); 3329 3330 pkiDebug("loading module \"%s\"... ", modname); 3331 /* Solaris Kerberos */ 3332 handle = dlopen(modname, RTLD_NOW | RTLD_GROUP); 3333 if (handle == NULL) { 3334 pkiDebug("not found\n"); 3335 return NULL; 3336 } 3337 getflist = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR)) dlsym(handle, "C_GetFunctionList"); 3338 if (getflist == NULL || (*getflist)(p11p) != CKR_OK) { 3339 (void) dlclose(handle); 3340 pkiDebug("failed\n"); 3341 return NULL; 3342 } 3343 pkiDebug("ok\n"); 3344 return handle; 3345 } 3346 3347 static CK_RV 3348 pkinit_C_UnloadModule(void *handle) 3349 { 3350 /* Solaris Kerberos */ 3351 if (dlclose(handle) != 0) 3352 return CKR_GENERAL_ERROR; 3353 3354 return CKR_OK; 3355 } 3356 3357 /* 3358 * Solaris Kerberos: this is a new function that does not exist yet in the MIT 3359 * code. 3360 * 3361 * labelstr will be C string containing token label with trailing white space 3362 * removed. 3363 */ 3364 static void 3365 trim_token_label(CK_TOKEN_INFO *tinfo, char *labelstr, unsigned int labelstr_len) 3366 { 3367 int i; 3368 3369 assert(labelstr_len > sizeof (tinfo->label)); 3370 /* 3371 * \0 terminate labelstr in case the last char in the token label is 3372 * non-whitespace 3373 */ 3374 labelstr[sizeof (tinfo->label)] = '\0'; 3375 (void) memcpy(labelstr, (char *) tinfo->label, sizeof (tinfo->label)); 3376 3377 /* init i so terminating \0 is skipped */ 3378 for (i = sizeof (tinfo->label) - 1; i >= 0; i--) { 3379 if (labelstr[i] == ' ') 3380 labelstr[i] = '\0'; 3381 else 3382 break; 3383 } 3384 } 3385 3386 /* 3387 * Solaris Kerberos: this is a new function that does not exist yet in the MIT 3388 * code. 3389 */ 3390 static krb5_error_code 3391 pkinit_prompt_user(krb5_context context, 3392 pkinit_identity_crypto_context cctx, 3393 krb5_data *reply, 3394 char *prompt, 3395 int hidden) 3396 { 3397 krb5_error_code r; 3398 krb5_prompt kprompt; 3399 krb5_prompt_type prompt_type; 3400 3401 if (cctx->prompter == NULL) 3402 return (EINVAL); 3403 3404 kprompt.prompt = prompt; 3405 kprompt.hidden = hidden; 3406 kprompt.reply = reply; 3407 /* 3408 * Note, assuming this type for now, may need to be passed in in the future. 3409 */ 3410 prompt_type = KRB5_PROMPT_TYPE_PREAUTH; 3411 3412 /* PROMPTER_INVOCATION */ 3413 k5int_set_prompt_types(context, &prompt_type); 3414 r = (*cctx->prompter)(context, cctx->prompter_data, 3415 NULL, NULL, 1, &kprompt); 3416 k5int_set_prompt_types(context, NULL); 3417 return (r); 3418 } 3419 3420 /* 3421 * Solaris Kerberos: this function was changed to support a PIN being passed 3422 * in. If that is the case the user will not be prompted for their PIN. 3423 */ 3424 static krb5_error_code 3425 pkinit_login(krb5_context context, 3426 pkinit_identity_crypto_context id_cryptoctx, 3427 CK_TOKEN_INFO *tip) 3428 { 3429 krb5_data rdat; 3430 char *prompt; 3431 int prompt_len; 3432 int r = 0; 3433 3434 if (tip->flags & CKF_PROTECTED_AUTHENTICATION_PATH) { 3435 rdat.data = NULL; 3436 rdat.length = 0; 3437 } else if (id_cryptoctx->PIN != NULL) { 3438 if ((rdat.data = strdup(id_cryptoctx->PIN)) == NULL) 3439 return (ENOMEM); 3440 /* 3441 * Don't include NULL string terminator in length calculation as this 3442 * PIN is passed to the C_Login function and only the text chars should 3443 * be considered to be the PIN. 3444 */ 3445 rdat.length = strlen(id_cryptoctx->PIN); 3446 } else { 3447 /* Solaris Kerberos - trim token label */ 3448 char tmplabel[sizeof (tip->label) + 1]; 3449 3450 if (!id_cryptoctx->prompter) { 3451 pkiDebug("pkinit_login: id_cryptoctx->prompter is NULL\n"); 3452 /* Solaris Kerberos: Improved error messages */ 3453 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, 3454 gettext("Failed to log into token: prompter function is NULL")); 3455 return (KRB5KDC_ERR_PREAUTH_FAILED); 3456 } 3457 /* Solaris Kerberos - Changes for gettext() */ 3458 prompt_len = sizeof (tip->label) + 256; 3459 if ((prompt = (char *) malloc(prompt_len)) == NULL) 3460 return ENOMEM; 3461 3462 /* Solaris Kerberos - trim token label which can be padded with space */ 3463 trim_token_label(tip, tmplabel, sizeof (tmplabel)); 3464 (void) snprintf(prompt, prompt_len, gettext("%s PIN"), tmplabel); 3465 3466 /* Solaris Kerberos */ 3467 if (tip->flags & CKF_USER_PIN_LOCKED) 3468 (void) strlcat(prompt, gettext(" (Warning: PIN locked)"), prompt_len); 3469 else if (tip->flags & CKF_USER_PIN_FINAL_TRY) 3470 (void) strlcat(prompt, gettext(" (Warning: PIN final try)"), prompt_len); 3471 else if (tip->flags & CKF_USER_PIN_COUNT_LOW) 3472 (void) strlcat(prompt, gettext(" (Warning: PIN count low)"), prompt_len); 3473 rdat.data = malloc(tip->ulMaxPinLen + 2); 3474 rdat.length = tip->ulMaxPinLen + 1; 3475 /* 3476 * Note that the prompter function will set rdat.length such that the 3477 * NULL terminator is not included 3478 */ 3479 /* PROMPTER_INVOCATION */ 3480 r = pkinit_prompt_user(context, id_cryptoctx, &rdat, prompt, 1); 3481 free(prompt); 3482 } 3483 3484 if (r == 0) { 3485 r = id_cryptoctx->p11->C_Login(id_cryptoctx->session, CKU_USER, 3486 (u_char *) rdat.data, rdat.length); 3487 3488 if (r != CKR_OK) { 3489 pkiDebug("C_Login: %s\n", pkinit_pkcs11_code_to_text(r)); 3490 /* Solaris Kerberos: Improved error messages */ 3491 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, 3492 gettext("Failed to log into token: %s"), 3493 pkinit_pkcs11_code_to_text(r)); 3494 r = KRB5KDC_ERR_PREAUTH_FAILED; 3495 } else { 3496 /* Solaris Kerberos: only need to login once */ 3497 id_cryptoctx->p11flags |= C_LOGIN_DONE; 3498 } 3499 } 3500 if (rdat.data) { 3501 (void) memset(rdat.data, 0, rdat.length); 3502 free(rdat.data); 3503 } 3504 3505 return (r); 3506 } 3507 3508 /* 3509 * Solaris Kerberos: added these structs in support of prompting user for 3510 * missing token. 3511 */ 3512 struct _token_entry { 3513 CK_SLOT_ID slotID; 3514 CK_SESSION_HANDLE session; 3515 CK_TOKEN_INFO token_info; 3516 }; 3517 struct _token_choices { 3518 unsigned int numtokens; 3519 struct _token_entry *token_array; 3520 }; 3521 3522 3523 /* 3524 * Solaris Kerberos: this is a new function that does not exist yet in the MIT 3525 * code. 3526 */ 3527 static krb5_error_code 3528 pkinit_prompt_token(krb5_context context, 3529 pkinit_identity_crypto_context cctx) 3530 { 3531 char tmpbuf[4]; 3532 krb5_data reply; 3533 char *token_prompt = gettext("If you have a smartcard insert it now. " 3534 "Press enter to continue"); 3535 3536 reply.data = tmpbuf; 3537 reply.length = sizeof(tmpbuf); 3538 3539 /* note, don't care about the reply */ 3540 return (pkinit_prompt_user(context, cctx, &reply, token_prompt, 0)); 3541 } 3542 3543 /* 3544 * Solaris Kerberos: new defines for prompting support. 3545 */ 3546 #define CHOOSE_THIS_TOKEN 0 3547 #define CHOOSE_RESCAN 1 3548 #define CHOOSE_SKIP 2 3549 #define CHOOSE_SEE_NEXT 3 3550 3551 #define RESCAN_TOKENS -1 3552 #define SKIP_TOKENS -2 3553 3554 /* 3555 * Solaris Kerberos: this is a new function that does not exist yet in the MIT 3556 * code. 3557 * 3558 * This prompts to user for various choices regarding a token to use. Note 3559 * that if there is no error, choice will be set to one of: 3560 * - the token_choices->token_array entry 3561 * - RESCAN_TOKENS 3562 * - SKIP_TOKENS 3563 */ 3564 static int 3565 pkinit_choose_tokens(krb5_context context, 3566 pkinit_identity_crypto_context cctx, 3567 struct _token_choices *token_choices, 3568 int *choice) 3569 { 3570 krb5_error_code r; 3571 /* 3572 * Assuming that PAM_MAX_MSG_SIZE is a reasonable restriction. Note that - 3573 * 2 is to account for the fact that a krb prompter to PAM conv bridge will 3574 * add ": ". 3575 */ 3576 char prompt[PAM_MAX_MSG_SIZE - 2]; 3577 char tmpbuf[4]; 3578 char tmplabel[sizeof (token_choices->token_array->token_info.label) + 1]; 3579 krb5_data reply; 3580 int i, num_used, tmpchoice; 3581 3582 assert(token_choices != NULL); 3583 assert(choice != NULL); 3584 3585 /* Create the menu prompt */ 3586 3587 /* only need to do this once before the for loop */ 3588 reply.data = tmpbuf; 3589 3590 for (i = 0; i < token_choices->numtokens; i++) { 3591 3592 trim_token_label(&token_choices->token_array[i].token_info, tmplabel, 3593 sizeof (tmplabel)); 3594 3595 if (i == (token_choices->numtokens - 1)) { 3596 /* no more smartcards/tokens */ 3597 if ((num_used = snprintf(prompt, sizeof (prompt), 3598 "%s\n%d: %s \"%s\" %s %d\n%d: %s\n%d: %s\n", 3599 /* 3600 * TRANSLATION_NOTE: Translations of the 3601 * following 5 strings must not exceed 450 3602 * bytes total. 3603 */ 3604 gettext("Select one of the following and press enter:"), 3605 CHOOSE_THIS_TOKEN, gettext("Use smartcard"), tmplabel, 3606 gettext("in slot"), token_choices->token_array[i].slotID, 3607 CHOOSE_RESCAN, gettext("Rescan for newly inserted smartcard"), 3608 CHOOSE_SKIP, gettext("Skip smartcard authentication"))) 3609 >= sizeof (prompt)) { 3610 pkiDebug("pkinit_choose_tokens: buffer overflow num_used: %d," 3611 " sizeof prompt: %d\n", num_used, sizeof (prompt)); 3612 krb5_set_error_message(context, EINVAL, 3613 gettext("In pkinit_choose_tokens: prompt size" 3614 " %d exceeds prompt buffer size %d"), 3615 num_used, sizeof(prompt)); 3616 (void) snprintf(prompt, sizeof (prompt), "%s", 3617 gettext("Error: PKINIT prompt message is too large for buffer, " 3618 "please alert the system administrator. Press enter to " 3619 "continue")); 3620 reply.length = sizeof(tmpbuf); 3621 if ((r = pkinit_prompt_user(context, cctx, &reply, prompt, 0)) != 0 ) 3622 return (r); 3623 return (EINVAL); 3624 } 3625 } else { 3626 if ((num_used = snprintf(prompt, sizeof (prompt), 3627 "%s\n%d: %s \"%s\" %s %d\n%d: %s\n%d: %s\n%d: %s\n", 3628 /* 3629 * TRANSLATION_NOTE: Translations of the 3630 * following 6 strings must not exceed 445 3631 * bytes total. 3632 */ 3633 gettext("Select one of the following and press enter:"), 3634 CHOOSE_THIS_TOKEN, gettext("Use smartcard"), tmplabel, 3635 gettext("in slot"), token_choices->token_array[i].slotID, 3636 CHOOSE_RESCAN, gettext("Rescan for newly inserted smartcard"), 3637 CHOOSE_SKIP, gettext("Skip smartcard authentication"), 3638 CHOOSE_SEE_NEXT, gettext("See next smartcard"))) 3639 >= sizeof (prompt)) { 3640 3641 pkiDebug("pkinit_choose_tokens: buffer overflow num_used: %d," 3642 " sizeof prompt: %d\n", num_used, sizeof (prompt)); 3643 krb5_set_error_message(context, EINVAL, 3644 gettext("In pkinit_choose_tokens: prompt size" 3645 " %d exceeds prompt buffer size %d"), 3646 num_used, sizeof(prompt)); 3647 (void) snprintf(prompt, sizeof (prompt), "%s", 3648 gettext("Error: PKINIT prompt message is too large for buffer, " 3649 "please alert the system administrator. Press enter to " 3650 "continue")); 3651 reply.length = sizeof(tmpbuf); 3652 if ((r = pkinit_prompt_user(context, cctx, &reply, prompt, 0)) != 0 ) 3653 return (r); 3654 return (EINVAL); 3655 } 3656 } 3657 3658 /* 3659 * reply.length needs to be reset to length of tmpbuf before calling 3660 * prompter 3661 */ 3662 reply.length = sizeof(tmpbuf); 3663 if ((r = pkinit_prompt_user(context, cctx, &reply, prompt, 0)) != 0 ) 3664 return (r); 3665 3666 if (reply.length == 0) { 3667 return (EINVAL); 3668 } else { 3669 char *cp = reply.data; 3670 /* reply better be digits */ 3671 while (*cp != NULL) { 3672 if (!isdigit(*cp++)) 3673 return (EINVAL); 3674 } 3675 errno = 0; 3676 tmpchoice = (int) strtol(reply.data, (char **)NULL, 10); 3677 if (errno != 0) 3678 return (errno); 3679 } 3680 3681 switch (tmpchoice) { 3682 case CHOOSE_THIS_TOKEN: 3683 *choice = i; /* chosen entry of token_choices->token_array */ 3684 return (0); 3685 case CHOOSE_RESCAN: 3686 *choice = RESCAN_TOKENS; /* rescan for new smartcard */ 3687 return (0); 3688 case CHOOSE_SKIP: 3689 *choice = SKIP_TOKENS; /* skip smartcard auth */ 3690 return (0); 3691 case CHOOSE_SEE_NEXT: /* see next smartcard */ 3692 continue; 3693 default: 3694 return (EINVAL); 3695 } 3696 } 3697 3698 return (0); 3699 } 3700 3701 /* 3702 * Solaris Kerberos: this is a new function that does not exist yet in the MIT 3703 * code. 3704 * 3705 * Note, this isn't the best solution to providing a function to check the 3706 * certs in a token however I wanted to avoid rewriting a bunch of code so I 3707 * settled for some duplication of processing. 3708 */ 3709 static krb5_error_code 3710 check_load_certs(krb5_context context, 3711 CK_SESSION_HANDLE session, 3712 pkinit_plg_crypto_context plg_cryptoctx, 3713 pkinit_req_crypto_context req_cryptoctx, 3714 pkinit_identity_crypto_context id_cryptoctx, 3715 krb5_principal princ, 3716 int do_matching, 3717 int load_cert) 3718 { 3719 CK_OBJECT_CLASS cls; 3720 CK_OBJECT_HANDLE obj; 3721 CK_ATTRIBUTE attrs[4]; 3722 CK_ULONG count; 3723 CK_CERTIFICATE_TYPE certtype; 3724 CK_BYTE_PTR cert = NULL, cert_id = NULL; 3725 const unsigned char *cp; 3726 int i, r; 3727 unsigned int nattrs; 3728 X509 *x = NULL; 3729 3730 cls = CKO_CERTIFICATE; 3731 attrs[0].type = CKA_CLASS; 3732 attrs[0].pValue = &cls; 3733 attrs[0].ulValueLen = sizeof cls; 3734 3735 certtype = CKC_X_509; 3736 attrs[1].type = CKA_CERTIFICATE_TYPE; 3737 attrs[1].pValue = &certtype; 3738 attrs[1].ulValueLen = sizeof certtype; 3739 3740 nattrs = 2; 3741 3742 /* If a cert id and/or label were given, use them too */ 3743 if (id_cryptoctx->cert_id_len > 0) { 3744 attrs[nattrs].type = CKA_ID; 3745 attrs[nattrs].pValue = id_cryptoctx->cert_id; 3746 attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len; 3747 nattrs++; 3748 } 3749 if (id_cryptoctx->cert_label != NULL) { 3750 attrs[nattrs].type = CKA_LABEL; 3751 attrs[nattrs].pValue = id_cryptoctx->cert_label; 3752 attrs[nattrs].ulValueLen = strlen(id_cryptoctx->cert_label); 3753 nattrs++; 3754 } 3755 3756 r = id_cryptoctx->p11->C_FindObjectsInit(session, attrs, nattrs); 3757 if (r != CKR_OK) { 3758 pkiDebug("C_FindObjectsInit: %s\n", pkinit_pkcs11_code_to_text(r)); 3759 krb5_set_error_message(context, EINVAL, 3760 gettext("PKCS11 error from C_FindObjectsInit: %s"), 3761 pkinit_pkcs11_code_to_text(r)); 3762 r = EINVAL; 3763 goto out; 3764 } 3765 3766 for (i = 0; ; i++) { 3767 if (i >= MAX_CREDS_ALLOWED) { 3768 r = EINVAL; 3769 goto out; 3770 } 3771 3772 /* Look for x.509 cert */ 3773 /* Solaris Kerberos */ 3774 if ((r = id_cryptoctx->p11->C_FindObjects(session, &obj, 1, &count)) 3775 != CKR_OK || count == 0) { 3776 id_cryptoctx->creds[i] = NULL; 3777 break; 3778 } 3779 3780 /* Get cert and id len */ 3781 attrs[0].type = CKA_VALUE; 3782 attrs[0].pValue = NULL; 3783 attrs[0].ulValueLen = 0; 3784 3785 attrs[1].type = CKA_ID; 3786 attrs[1].pValue = NULL; 3787 attrs[1].ulValueLen = 0; 3788 3789 if ((r = id_cryptoctx->p11->C_GetAttributeValue(session, 3790 obj, 3791 attrs, 3792 2)) != CKR_OK && 3793 r != CKR_BUFFER_TOO_SMALL) { 3794 pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r)); 3795 krb5_set_error_message(context, EINVAL, 3796 gettext("Error from PKCS11 C_GetAttributeValue: %s"), 3797 pkinit_pkcs11_code_to_text(r)); 3798 r = EINVAL; 3799 goto out; 3800 } 3801 cert = malloc((size_t) attrs[0].ulValueLen + 1); 3802 if (cert == NULL) { 3803 r = ENOMEM; 3804 goto out; 3805 } 3806 cert_id = malloc((size_t) attrs[1].ulValueLen + 1); 3807 if (cert_id == NULL) { 3808 r = ENOMEM; 3809 goto out; 3810 } 3811 3812 /* Read the cert and id off the card */ 3813 3814 attrs[0].type = CKA_VALUE; 3815 attrs[0].pValue = cert; 3816 3817 attrs[1].type = CKA_ID; 3818 attrs[1].pValue = cert_id; 3819 3820 if ((r = id_cryptoctx->p11->C_GetAttributeValue(session, 3821 obj, attrs, 2)) != CKR_OK) { 3822 pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r)); 3823 krb5_set_error_message(context, EINVAL, 3824 gettext("Error from PKCS11 C_GetAttributeValue: %s"), 3825 pkinit_pkcs11_code_to_text(r)); 3826 r = EINVAL; 3827 goto out; 3828 } 3829 3830 pkiDebug("cert %d size %d id %d idlen %d\n", i, 3831 (int) attrs[0].ulValueLen, (int) cert_id[0], 3832 (int) attrs[1].ulValueLen); 3833 3834 cp = (unsigned char *) cert; 3835 x = d2i_X509(NULL, &cp, (int) attrs[0].ulValueLen); 3836 if (x == NULL) { 3837 r = EINVAL; 3838 goto out; 3839 } 3840 3841 id_cryptoctx->creds[i] = malloc(sizeof(struct _pkinit_cred_info)); 3842 if (id_cryptoctx->creds[i] == NULL) { 3843 r = ENOMEM; 3844 goto out; 3845 } 3846 id_cryptoctx->creds[i]->cert = x; 3847 id_cryptoctx->creds[i]->key = NULL; 3848 id_cryptoctx->creds[i]->cert_id = cert_id; 3849 cert_id = NULL; 3850 id_cryptoctx->creds[i]->cert_id_len = attrs[1].ulValueLen; 3851 free(cert); 3852 cert = NULL; 3853 } 3854 id_cryptoctx->p11->C_FindObjectsFinal(session); 3855 3856 if (id_cryptoctx->creds[0] == NULL || id_cryptoctx->creds[0]->cert == NULL) { 3857 r = ENOENT; 3858 } else if (do_matching){ 3859 /* 3860 * Do not let pkinit_cert_matching set the primary cert in id_cryptoctx 3861 * as this will be done later. 3862 */ 3863 r = pkinit_cert_matching(context, plg_cryptoctx, req_cryptoctx, 3864 id_cryptoctx, princ, FALSE); 3865 } 3866 3867 out: 3868 if ((r != 0 || !load_cert) && 3869 id_cryptoctx->creds[0] != NULL && 3870 id_cryptoctx->creds[0]->cert != NULL) { 3871 /* 3872 * If there's an error or load_cert isn't 1 free all the certs loaded 3873 * onto id_cryptoctx. 3874 */ 3875 (void) crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx, 3876 id_cryptoctx); 3877 } 3878 3879 if (cert) 3880 free(cert); 3881 3882 if (cert_id) 3883 free(cert_id); 3884 3885 return (r); 3886 } 3887 3888 /* 3889 * Solaris Kerberos: this function has been significantly modified to prompt 3890 * the user in certain cases so defer to this version when resyncing MIT code. 3891 * 3892 * pkinit_open_session now does several things including prompting the user if 3893 * do_matching is set which indicates the code is executing in a client 3894 * context. This function fills out a pkinit_identity_crypto_context with a 3895 * set of certs and a open session if a token can be found that matches all 3896 * supplied criteria. If no token is found then the user is prompted one time 3897 * to insert their token. If there is more than one token that matches all 3898 * client criteria the user is prompted to make a choice if in client context. 3899 * If do_matching is false (KDC context) then the first token matching all 3900 * server criteria is chosen. 3901 */ 3902 static krb5_error_code 3903 pkinit_open_session(krb5_context context, 3904 pkinit_plg_crypto_context plg_cryptoctx, 3905 pkinit_req_crypto_context req_cryptoctx, 3906 pkinit_identity_crypto_context cctx, 3907 krb5_principal princ, 3908 int do_matching) 3909 { 3910 int i, r; 3911 CK_ULONG count = 0; 3912 CK_SLOT_ID_PTR slotlist = NULL, tmpslotlist = NULL; 3913 CK_TOKEN_INFO tinfo; 3914 krb5_boolean tokenmatch = FALSE; 3915 CK_SESSION_HANDLE tmpsession = NULL; 3916 struct _token_choices token_choices; 3917 int choice = 0; 3918 3919 if (cctx->session != CK_INVALID_HANDLE) 3920 return 0; /* session already open */ 3921 3922 /* Load module */ 3923 if (cctx->p11_module == NULL) { 3924 cctx->p11_module = 3925 pkinit_C_LoadModule(cctx->p11_module_name, &cctx->p11); 3926 if (cctx->p11_module == NULL) 3927 return KRB5KDC_ERR_PREAUTH_FAILED; 3928 } 3929 3930 /* Init */ 3931 /* Solaris Kerberos: Don't fail if cryptoki is already initialized */ 3932 r = cctx->p11->C_Initialize(NULL); 3933 if (r != CKR_OK && r != CKR_CRYPTOKI_ALREADY_INITIALIZED) { 3934 pkiDebug("C_Initialize: %s\n", pkinit_pkcs11_code_to_text(r)); 3935 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, 3936 gettext("Error from PKCS11 C_Initialize: %s"), 3937 pkinit_pkcs11_code_to_text(r)); 3938 return KRB5KDC_ERR_PREAUTH_FAILED; 3939 } 3940 3941 (void) memset(&token_choices, 0, sizeof(token_choices)); 3942 3943 /* 3944 * Solaris Kerberos: 3945 * If C_Initialize was already called by the process before the pkinit 3946 * module was loaded then record that fact. 3947 * "finalize_pkcs11" is used by pkinit_fini_pkcs11 to determine whether 3948 * or not C_Finalize() should be called. 3949 */ 3950 cctx->finalize_pkcs11 = 3951 (r == CKR_CRYPTOKI_ALREADY_INITIALIZED ? FALSE : TRUE); 3952 /* 3953 * First make sure that is an applicable slot otherwise fail. 3954 * 3955 * Start by getting a count of all slots with or without tokens. 3956 */ 3957 3958 if ((r = cctx->p11->C_GetSlotList(FALSE, NULL, &count)) != CKR_OK) { 3959 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r)); 3960 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, 3961 gettext("Error trying to get PKCS11 slot list: %s"), 3962 pkinit_pkcs11_code_to_text(r)); 3963 r = KRB5KDC_ERR_PREAUTH_FAILED; 3964 goto out; 3965 } 3966 3967 if (count == 0) { 3968 /* There are no slots so bail */ 3969 r = KRB5KDC_ERR_PREAUTH_FAILED; 3970 krb5_set_error_message(context, r, 3971 gettext("No PKCS11 slots found")); 3972 pkiDebug("pkinit_open_session: no slots, count: %d\n", count); 3973 goto out; 3974 } else if (cctx->slotid != PK_NOSLOT) { 3975 /* See if any of the slots match the specified slotID */ 3976 tmpslotlist = malloc(count * sizeof (CK_SLOT_ID)); 3977 if (tmpslotlist == NULL) { 3978 krb5_set_error_message(context, ENOMEM, 3979 gettext("Memory allocation error:")); 3980 r = KRB5KDC_ERR_PREAUTH_FAILED; 3981 goto out; 3982 } 3983 if ((r = cctx->p11->C_GetSlotList(FALSE, tmpslotlist, &count)) != CKR_OK) { 3984 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, 3985 gettext("Error trying to get PKCS11 slot list: %s"), 3986 pkinit_pkcs11_code_to_text(r)); 3987 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r)); 3988 r = KRB5KDC_ERR_PREAUTH_FAILED; 3989 goto out; 3990 } 3991 3992 for (i = 0; i < count && cctx->slotid != tmpslotlist[i]; i++) 3993 continue; 3994 3995 if (i >= count) { 3996 /* no slots match */ 3997 r = KRB5KDC_ERR_PREAUTH_FAILED; 3998 krb5_set_error_message(context, r, 3999 gettext("Requested PKCS11 slot ID %d not found"), 4000 cctx->slotid); 4001 pkiDebug("open_session: no matching slot found for slotID %d\n", 4002 cctx->slotid); 4003 goto out; 4004 } 4005 } 4006 4007 tryagain: 4008 /* get count of slots that have tokens */ 4009 if ((r = cctx->p11->C_GetSlotList(TRUE, NULL, &count)) != CKR_OK) { 4010 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r)); 4011 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, 4012 gettext("Error trying to get PKCS11 slot list: %s"), 4013 pkinit_pkcs11_code_to_text(r)); 4014 r = KRB5KDC_ERR_PREAUTH_FAILED; 4015 goto out; 4016 } 4017 4018 if (count == 0) { 4019 /* 4020 * Note, never prompt if !do_matching as this implies KDC side 4021 * processing 4022 */ 4023 if (!(cctx->p11flags & C_PROMPTED_USER) && do_matching) { 4024 /* found slot(s) but no token so prompt and try again */ 4025 if ((r = pkinit_prompt_token(context, cctx)) == 0) { 4026 cctx->p11flags |= C_PROMPTED_USER; 4027 goto tryagain; 4028 } else { 4029 pkiDebug("open_session: prompt for token/smart card failed\n"); 4030 krb5_set_error_message(context, r, 4031 gettext("Prompt for token/smart card failed")); 4032 r = KRB5KDC_ERR_PREAUTH_FAILED; 4033 goto out; 4034 } 4035 4036 } else { 4037 /* already prompted once so bailing */ 4038 r = KRB5KDC_ERR_PREAUTH_FAILED; 4039 krb5_set_error_message(context, r, 4040 gettext("No smart card tokens found")); 4041 pkiDebug("pkinit_open_session: no token, already prompted\n"); 4042 goto out; 4043 } 4044 } 4045 4046 if (slotlist != NULL) 4047 free(slotlist); 4048 4049 slotlist = malloc(count * sizeof (CK_SLOT_ID)); 4050 if (slotlist == NULL) { 4051 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, 4052 gettext("Memory allocation error")); 4053 r = KRB5KDC_ERR_PREAUTH_FAILED; 4054 goto out; 4055 } 4056 /* 4057 * Solaris Kerberos: get list of PKCS11 slotid's that have tokens. 4058 */ 4059 if (cctx->p11->C_GetSlotList(TRUE, slotlist, &count) != CKR_OK) { 4060 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, 4061 gettext("Error trying to get PKCS11 slot list: %s"), 4062 pkinit_pkcs11_code_to_text(r)); 4063 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r)); 4064 r = KRB5KDC_ERR_PREAUTH_FAILED; 4065 goto out; 4066 } 4067 4068 token_choices.numtokens = 0; 4069 token_choices.token_array = malloc(count * sizeof (*token_choices.token_array)); 4070 if (token_choices.token_array == NULL) { 4071 r = KRB5KDC_ERR_PREAUTH_FAILED; 4072 krb5_set_error_message(context, r, 4073 gettext("Memory allocation error")); 4074 goto out; 4075 } 4076 4077 /* examine all the tokens */ 4078 for (i = 0; i < count; i++) { 4079 /* 4080 * Solaris Kerberos: if a slotid was specified skip slots that don't 4081 * match. 4082 */ 4083 if (cctx->slotid != PK_NOSLOT && cctx->slotid != slotlist[i]) 4084 continue; 4085 4086 /* Open session */ 4087 if ((r = cctx->p11->C_OpenSession(slotlist[i], CKF_SERIAL_SESSION, 4088 NULL, NULL, &tmpsession)) != CKR_OK) { 4089 pkiDebug("C_OpenSession: %s\n", pkinit_pkcs11_code_to_text(r)); 4090 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, 4091 gettext("Error trying to open PKCS11 session: %s"), 4092 pkinit_pkcs11_code_to_text(r)); 4093 r = KRB5KDC_ERR_PREAUTH_FAILED; 4094 goto out; 4095 } 4096 4097 /* Get token info */ 4098 if ((r = cctx->p11->C_GetTokenInfo(slotlist[i], &tinfo)) != CKR_OK) { 4099 pkiDebug("C_GetTokenInfo: %s\n", pkinit_pkcs11_code_to_text(r)); 4100 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, 4101 gettext("Error trying to read PKCS11 token: %s"), 4102 pkinit_pkcs11_code_to_text(r)); 4103 r = KRB5KDC_ERR_PREAUTH_FAILED; 4104 cctx->p11->C_CloseSession(tmpsession); 4105 goto out; 4106 } 4107 4108 if (cctx->token_label == NULL) { 4109 /* 4110 * If the token doesn't require login to examine the certs then 4111 * let's check the certs out to see if any match the criteria if 4112 * any. 4113 */ 4114 if (!(tinfo.flags & CKF_LOGIN_REQUIRED)) { 4115 /* 4116 * It's okay to check the certs if we don't have to login but 4117 * don't load the certs onto cctx at this point, this will be 4118 * done later in this function for the chosen token. 4119 */ 4120 if ((r = check_load_certs(context, tmpsession, plg_cryptoctx, 4121 req_cryptoctx, cctx, princ, 4122 do_matching, 0)) == 0) { 4123 tokenmatch = TRUE; 4124 } else if (r != ENOENT){ 4125 r = KRB5KDC_ERR_PREAUTH_FAILED; 4126 cctx->p11->C_CloseSession(tmpsession); 4127 goto out; 4128 } else { 4129 /* ignore ENOENT here */ 4130 r = 0; 4131 } 4132 } else { 4133 tokenmatch = TRUE; 4134 } 4135 } else { 4136 /* + 1 so tokenlabelstr can be \0 terminated */ 4137 char tokenlabelstr[sizeof (tinfo.label) + 1]; 4138 4139 /* 4140 * Convert token label into C string with trailing white space 4141 * trimmed. 4142 */ 4143 trim_token_label(&tinfo, tokenlabelstr, sizeof (tokenlabelstr)); 4144 4145 pkiDebug("open_session: slotid %d token found: \"%s\", " 4146 "cctx->token_label: \"%s\"\n", 4147 slotlist[i], tokenlabelstr, (char *) cctx->token_label); 4148 4149 if (!strcmp(cctx->token_label, tokenlabelstr)) { 4150 if (!(tinfo.flags & CKF_LOGIN_REQUIRED)) { 4151 /* 4152 * It's okay to check the certs if we don't have to login but 4153 * don't load the certs onto cctx at this point, this will be 4154 * done later in this function for the chosen token. 4155 */ 4156 if ((r = check_load_certs(context, tmpsession, plg_cryptoctx, 4157 req_cryptoctx, cctx, princ, 4158 do_matching, 0)) == 0) { 4159 tokenmatch = TRUE; 4160 } else if (r != ENOENT){ 4161 r = KRB5KDC_ERR_PREAUTH_FAILED; 4162 cctx->p11->C_CloseSession(tmpsession); 4163 goto out; 4164 } else { 4165 /* ignore ENOENT here */ 4166 r = 0; 4167 } 4168 } else { 4169 tokenmatch = TRUE; 4170 } 4171 } 4172 } 4173 4174 if (tokenmatch == TRUE) { 4175 /* add the token to token_choices.token_array */ 4176 token_choices.token_array[token_choices.numtokens].slotID = slotlist[i]; 4177 token_choices.token_array[token_choices.numtokens].session = tmpsession; 4178 token_choices.token_array[token_choices.numtokens].token_info = tinfo; 4179 token_choices.numtokens++; 4180 /* !do_matching implies we take the first matching token */ 4181 if (!do_matching) 4182 break; 4183 else 4184 tokenmatch = FALSE; 4185 } else { 4186 cctx->p11->C_CloseSession(tmpsession); 4187 } 4188 } 4189 4190 if (token_choices.numtokens == 0) { 4191 /* 4192 * Solaris Kerberos: prompt for token one time if there was no token 4193 * and do_matching is 1 (see earlier comment about do_matching). 4194 */ 4195 if (!(cctx->p11flags & C_PROMPTED_USER) && do_matching) { 4196 if ((r = pkinit_prompt_token(context, cctx)) == 0) { 4197 cctx->p11flags |= C_PROMPTED_USER; 4198 goto tryagain; 4199 } else { 4200 pkiDebug("open_session: prompt for token/smart card failed\n"); 4201 krb5_set_error_message(context, r, 4202 gettext("Prompt for token/smart card failed")); 4203 r = KRB5KDC_ERR_PREAUTH_FAILED; 4204 goto out; 4205 } 4206 } else { 4207 r = KRB5KDC_ERR_PREAUTH_FAILED; 4208 krb5_set_error_message(context, r, 4209 gettext("No smart card tokens found")); 4210 pkiDebug("open_session: no matching token found\n"); 4211 goto out; 4212 } 4213 } else if (token_choices.numtokens == 1) { 4214 if ((token_choices.token_array[0].token_info.flags & CKF_LOGIN_REQUIRED) && 4215 !(cctx->p11flags & C_PROMPTED_USER) && 4216 do_matching) { 4217 if ((r = pkinit_choose_tokens(context, cctx, &token_choices, &choice)) != 0) { 4218 pkiDebug("pkinit_open_session: pkinit_choose_tokens failed: %d\n", r); 4219 r = KRB5KDC_ERR_PREAUTH_FAILED; 4220 krb5_set_error_message(context, r, 4221 gettext("Prompt for token/smart card failed")); 4222 goto out; 4223 } 4224 if (choice == RESCAN_TOKENS) { 4225 /* rescan for new smartcard/token */ 4226 for (i = 0; i < token_choices.numtokens; i++) { 4227 /* close all sessions */ 4228 cctx->p11->C_CloseSession(token_choices.token_array[i].session); 4229 } 4230 free(token_choices.token_array); 4231 token_choices.token_array = NULL; 4232 token_choices.numtokens = 0; 4233 goto tryagain; 4234 } else if (choice == SKIP_TOKENS) { 4235 /* do not use smartcard/token for auth */ 4236 cctx->p11flags |= (C_PROMPTED_USER|C_SKIP_PKCS11_AUTH); 4237 r = KRB5KDC_ERR_PREAUTH_FAILED; 4238 goto out; 4239 } else { 4240 cctx->p11flags |= C_PROMPTED_USER; 4241 } 4242 } else { 4243 choice = 0; /* really the only choice is the first token_array entry */ 4244 } 4245 } else if (!(cctx->p11flags & C_PROMPTED_USER) && do_matching) { 4246 /* > 1 token so present menu of token choices, let the user decide. */ 4247 if ((r = pkinit_choose_tokens(context, cctx, &token_choices, &choice)) != 0) { 4248 pkiDebug("pkinit_open_session: pkinit_choose_tokens failed: %d\n", r); 4249 r = KRB5KDC_ERR_PREAUTH_FAILED; 4250 krb5_set_error_message(context, r, 4251 gettext("Prompt for token/smart card failed")); 4252 goto out; 4253 } 4254 if (choice == RESCAN_TOKENS) { 4255 /* rescan for new smartcard/token */ 4256 for (i = 0; i < token_choices.numtokens; i++) { 4257 /* close all sessions */ 4258 cctx->p11->C_CloseSession(token_choices.token_array[i].session); 4259 } 4260 free(token_choices.token_array); 4261 token_choices.token_array = NULL; 4262 token_choices.numtokens = 0; 4263 goto tryagain; 4264 } else if (choice == SKIP_TOKENS) { 4265 /* do not use smartcard/token for auth */ 4266 cctx->p11flags |= (C_PROMPTED_USER|C_SKIP_PKCS11_AUTH); 4267 r = KRB5KDC_ERR_PREAUTH_FAILED; 4268 goto out; 4269 } else { 4270 cctx->p11flags |= C_PROMPTED_USER; 4271 } 4272 } else { 4273 r = KRB5KDC_ERR_PREAUTH_FAILED; 4274 goto out; 4275 } 4276 4277 cctx->slotid = token_choices.token_array[choice].slotID; 4278 cctx->session = token_choices.token_array[choice].session; 4279 4280 pkiDebug("open_session: slotid %d (%d of %d)\n", (int) cctx->slotid, 4281 i + 1, (int) count); 4282 4283 /* Login if needed */ 4284 /* Solaris Kerberos: added cctx->p11flags check */ 4285 if ((token_choices.token_array[choice].token_info.flags & CKF_LOGIN_REQUIRED) && 4286 !(cctx->p11flags & C_LOGIN_DONE)) { 4287 r = pkinit_login(context, cctx, &token_choices.token_array[choice].token_info); 4288 } 4289 4290 if (r == 0) { 4291 /* Doing this again to load the certs into cctx. */ 4292 r = check_load_certs(context, cctx->session, plg_cryptoctx, 4293 req_cryptoctx, cctx, princ, do_matching, 1); 4294 } 4295 4296 out: 4297 if (slotlist != NULL) 4298 free(slotlist); 4299 4300 if (tmpslotlist != NULL) 4301 free(tmpslotlist); 4302 4303 if (token_choices.token_array != NULL) { 4304 if (r != 0) { 4305 /* close all sessions if there's an error */ 4306 for (i = 0; i < token_choices.numtokens; i++) { 4307 cctx->p11->C_CloseSession(token_choices.token_array[i].session); 4308 } 4309 cctx->session = CK_INVALID_HANDLE; 4310 } else { 4311 /* close sessions not chosen */ 4312 for (i = 0; i < token_choices.numtokens; i++) { 4313 if (i != choice) { 4314 cctx->p11->C_CloseSession(token_choices.token_array[i].session); 4315 } 4316 } 4317 } 4318 free(token_choices.token_array); 4319 } 4320 4321 return (r); 4322 } 4323 4324 /* 4325 * Look for a key that's: 4326 * 1. private 4327 * 2. capable of the specified operation (usually signing or decrypting) 4328 * 3. RSA (this may be wrong but it's all we can do for now) 4329 * 4. matches the id of the cert we chose 4330 * 4331 * You must call pkinit_get_certs before calling pkinit_find_private_key 4332 * (that's because we need the ID of the private key) 4333 * 4334 * pkcs11 says the id of the key doesn't have to match that of the cert, but 4335 * I can't figure out any other way to decide which key to use. 4336 * 4337 * We should only find one key that fits all the requirements. 4338 * If there are more than one, we just take the first one. 4339 */ 4340 4341 /* ARGSUSED */ 4342 krb5_error_code 4343 pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx, 4344 CK_ATTRIBUTE_TYPE usage, 4345 CK_OBJECT_HANDLE *objp) 4346 { 4347 CK_OBJECT_CLASS cls; 4348 CK_ATTRIBUTE attrs[4]; 4349 CK_ULONG count; 4350 CK_KEY_TYPE keytype; 4351 unsigned int nattrs = 0; 4352 int r; 4353 #ifdef PKINIT_USE_KEY_USAGE 4354 CK_BBOOL true_false; 4355 #endif 4356 4357 cls = CKO_PRIVATE_KEY; 4358 attrs[nattrs].type = CKA_CLASS; 4359 attrs[nattrs].pValue = &cls; 4360 attrs[nattrs].ulValueLen = sizeof cls; 4361 nattrs++; 4362 4363 #ifdef PKINIT_USE_KEY_USAGE 4364 /* 4365 * Some cards get confused if you try to specify a key usage, 4366 * so don't, and hope for the best. This will fail if you have 4367 * several keys with the same id and different usages but I have 4368 * not seen this on real cards. 4369 */ 4370 true_false = TRUE; 4371 attrs[nattrs].type = usage; 4372 attrs[nattrs].pValue = &true_false; 4373 attrs[nattrs].ulValueLen = sizeof true_false; 4374 nattrs++; 4375 #endif 4376 4377 keytype = CKK_RSA; 4378 attrs[nattrs].type = CKA_KEY_TYPE; 4379 attrs[nattrs].pValue = &keytype; 4380 attrs[nattrs].ulValueLen = sizeof keytype; 4381 nattrs++; 4382 4383 attrs[nattrs].type = CKA_ID; 4384 attrs[nattrs].pValue = id_cryptoctx->cert_id; 4385 attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len; 4386 nattrs++; 4387 4388 r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs); 4389 if (r != CKR_OK) { 4390 pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n", 4391 pkinit_pkcs11_code_to_text(r)); 4392 return KRB5KDC_ERR_PREAUTH_FAILED; 4393 } 4394 4395 r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, objp, 1, &count); 4396 id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session); 4397 pkiDebug("found %d private keys (%s)\n", (int) count, pkinit_pkcs11_code_to_text(r)); 4398 4399 /* 4400 * Solaris Kerberos: 4401 * The CKA_ID may not be correctly set for the private key. For e.g. when 4402 * storing a private key in softtoken pktool(1) doesn't generate or store 4403 * a CKA_ID for the private key. Another way to identify the private key is 4404 * to look for a private key with the same RSA modulus as the public key 4405 * in the certificate. 4406 */ 4407 if (r == CKR_OK && count != 1) { 4408 4409 EVP_PKEY *priv; 4410 X509 *cert; 4411 unsigned int n_len; 4412 unsigned char *n_bytes; 4413 4414 cert = sk_X509_value(id_cryptoctx->my_certs, 0); 4415 priv = X509_get_pubkey(cert); 4416 if (priv == NULL) { 4417 pkiDebug("Failed to extract pub key from cert\n"); 4418 return KRB5KDC_ERR_PREAUTH_FAILED; 4419 } 4420 4421 nattrs = 0; 4422 cls = CKO_PRIVATE_KEY; 4423 attrs[nattrs].type = CKA_CLASS; 4424 attrs[nattrs].pValue = &cls; 4425 attrs[nattrs].ulValueLen = sizeof cls; 4426 nattrs++; 4427 4428 #ifdef PKINIT_USE_KEY_USAGE 4429 true_false = TRUE; 4430 attrs[nattrs].type = usage; 4431 attrs[nattrs].pValue = &true_false; 4432 attrs[nattrs].ulValueLen = sizeof true_false; 4433 nattrs++; 4434 #endif 4435 4436 keytype = CKK_RSA; 4437 attrs[nattrs].type = CKA_KEY_TYPE; 4438 attrs[nattrs].pValue = &keytype; 4439 attrs[nattrs].ulValueLen = sizeof keytype; 4440 nattrs++; 4441 4442 n_len = BN_num_bytes(priv->pkey.rsa->n); 4443 n_bytes = (unsigned char *) malloc((size_t) n_len); 4444 if (n_bytes == NULL) { 4445 return (ENOMEM); 4446 } 4447 4448 if (BN_bn2bin(priv->pkey.rsa->n, n_bytes) == 0) { 4449 free (n_bytes); 4450 pkiDebug("zero-byte key modulus\n"); 4451 return KRB5KDC_ERR_PREAUTH_FAILED; 4452 } 4453 4454 attrs[nattrs].type = CKA_MODULUS; 4455 attrs[nattrs].ulValueLen = n_len; 4456 attrs[nattrs].pValue = n_bytes; 4457 4458 nattrs++; 4459 4460 r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs); 4461 free (n_bytes); 4462 if (r != CKR_OK) { 4463 pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n", 4464 pkinit_pkcs11_code_to_text(r)); 4465 return KRB5KDC_ERR_PREAUTH_FAILED; 4466 } 4467 4468 r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, objp, 1, &count); 4469 id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session); 4470 pkiDebug("found %d private keys (%s)\n", (int) count, pkinit_pkcs11_code_to_text(r)); 4471 4472 } 4473 4474 if (r != CKR_OK || count < 1) 4475 return KRB5KDC_ERR_PREAUTH_FAILED; 4476 return 0; 4477 } 4478 #endif 4479 4480 /* ARGSUSED */ 4481 static krb5_error_code 4482 pkinit_decode_data_fs(krb5_context context, 4483 pkinit_identity_crypto_context id_cryptoctx, 4484 unsigned char *data, 4485 unsigned int data_len, 4486 unsigned char **decoded_data, 4487 unsigned int *decoded_data_len) 4488 { 4489 if (decode_data(decoded_data, decoded_data_len, data, data_len, 4490 id_cryptoctx->my_key, sk_X509_value(id_cryptoctx->my_certs, 4491 id_cryptoctx->cert_index)) <= 0) { 4492 pkiDebug("failed to decode data\n"); 4493 return KRB5KDC_ERR_PREAUTH_FAILED; 4494 } 4495 return 0; 4496 } 4497 4498 #ifndef WITHOUT_PKCS11 4499 #ifdef SILLYDECRYPT 4500 CK_RV 4501 pkinit_C_Decrypt(pkinit_identity_crypto_context id_cryptoctx, 4502 CK_BYTE_PTR pEncryptedData, 4503 CK_ULONG ulEncryptedDataLen, 4504 CK_BYTE_PTR pData, 4505 CK_ULONG_PTR pulDataLen) 4506 { 4507 CK_RV rv = CKR_OK; 4508 4509 rv = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, pEncryptedData, 4510 ulEncryptedDataLen, pData, pulDataLen); 4511 if (rv == CKR_OK) { 4512 pkiDebug("pData %x *pulDataLen %d\n", (int) pData, (int) *pulDataLen); 4513 } 4514 return rv; 4515 } 4516 #endif 4517 4518 static krb5_error_code 4519 pkinit_decode_data_pkcs11(krb5_context context, 4520 pkinit_identity_crypto_context id_cryptoctx, 4521 unsigned char *data, 4522 unsigned int data_len, 4523 unsigned char **decoded_data, 4524 unsigned int *decoded_data_len) 4525 { 4526 CK_OBJECT_HANDLE obj; 4527 CK_ULONG len; 4528 CK_MECHANISM mech; 4529 unsigned char *cp; 4530 int r; 4531 4532 /* 4533 * Solaris Kerberos: assume session is open and libpkcs11 funcs have been 4534 * loaded. 4535 */ 4536 assert(id_cryptoctx->p11 != NULL); 4537 4538 /* Solaris Kerberos: Login, if needed, to access private object */ 4539 if (!(id_cryptoctx->p11flags & C_LOGIN_DONE)) { 4540 CK_TOKEN_INFO tinfo; 4541 4542 r = id_cryptoctx->p11->C_GetTokenInfo(id_cryptoctx->slotid, &tinfo); 4543 if (r != 0) 4544 return r; 4545 4546 r = pkinit_login(context, id_cryptoctx, &tinfo); 4547 if (r != 0) 4548 return r; 4549 } 4550 4551 r = pkinit_find_private_key(id_cryptoctx, CKA_DECRYPT, &obj); 4552 if (r != 0) 4553 return r; 4554 4555 mech.mechanism = CKM_RSA_PKCS; 4556 mech.pParameter = NULL; 4557 mech.ulParameterLen = 0; 4558 4559 if ((r = id_cryptoctx->p11->C_DecryptInit(id_cryptoctx->session, &mech, 4560 obj)) != CKR_OK) { 4561 pkiDebug("C_DecryptInit: 0x%x\n", (int) r); 4562 return KRB5KDC_ERR_PREAUTH_FAILED; 4563 } 4564 pkiDebug("data_len = %d\n", data_len); 4565 cp = (unsigned char *)malloc((size_t) data_len); 4566 if (cp == NULL) 4567 return ENOMEM; 4568 len = data_len; 4569 #ifdef SILLYDECRYPT 4570 pkiDebug("session %x edata %x edata_len %d data %x datalen @%x %d\n", 4571 (int) id_cryptoctx->session, (int) data, (int) data_len, (int) cp, 4572 (int) &len, (int) len); 4573 if ((r = pkinit_C_Decrypt(id_cryptoctx, data, (CK_ULONG) data_len, 4574 cp, &len)) != CKR_OK) { 4575 #else 4576 if ((r = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, data, 4577 (CK_ULONG) data_len, cp, &len)) != CKR_OK) { 4578 #endif 4579 pkiDebug("C_Decrypt: %s\n", pkinit_pkcs11_code_to_text(r)); 4580 if (r == CKR_BUFFER_TOO_SMALL) 4581 pkiDebug("decrypt %d needs %d\n", (int) data_len, (int) len); 4582 return KRB5KDC_ERR_PREAUTH_FAILED; 4583 } 4584 pkiDebug("decrypt %d -> %d\n", (int) data_len, (int) len); 4585 *decoded_data_len = len; 4586 *decoded_data = cp; 4587 4588 return 0; 4589 } 4590 #endif 4591 4592 krb5_error_code 4593 pkinit_decode_data(krb5_context context, 4594 pkinit_identity_crypto_context id_cryptoctx, 4595 unsigned char *data, 4596 unsigned int data_len, 4597 unsigned char **decoded_data, 4598 unsigned int *decoded_data_len) 4599 { 4600 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; 4601 4602 if (id_cryptoctx->pkcs11_method != 1) 4603 retval = pkinit_decode_data_fs(context, id_cryptoctx, data, data_len, 4604 decoded_data, decoded_data_len); 4605 #ifndef WITHOUT_PKCS11 4606 else 4607 retval = pkinit_decode_data_pkcs11(context, id_cryptoctx, data, 4608 data_len, decoded_data, decoded_data_len); 4609 #endif 4610 4611 return retval; 4612 } 4613 4614 /* ARGSUSED */ 4615 static krb5_error_code 4616 pkinit_sign_data_fs(krb5_context context, 4617 pkinit_identity_crypto_context id_cryptoctx, 4618 unsigned char *data, 4619 unsigned int data_len, 4620 unsigned char **sig, 4621 unsigned int *sig_len) 4622 { 4623 if (create_signature(sig, sig_len, data, data_len, 4624 id_cryptoctx->my_key) != 0) { 4625 pkiDebug("failed to create the signature\n"); 4626 return KRB5KDC_ERR_PREAUTH_FAILED; 4627 } 4628 return 0; 4629 } 4630 4631 #ifndef WITHOUT_PKCS11 4632 static krb5_error_code 4633 pkinit_sign_data_pkcs11(krb5_context context, 4634 pkinit_identity_crypto_context id_cryptoctx, 4635 unsigned char *data, 4636 unsigned int data_len, 4637 unsigned char **sig, 4638 unsigned int *sig_len) 4639 { 4640 CK_OBJECT_HANDLE obj; 4641 CK_ULONG len; 4642 CK_MECHANISM mech; 4643 unsigned char *cp; 4644 int r; 4645 4646 /* 4647 * Solaris Kerberos: assume session is open and libpkcs11 funcs have been 4648 * loaded. 4649 */ 4650 assert(id_cryptoctx->p11 != NULL); 4651 4652 /* Solaris Kerberos: Login, if needed, to access private object */ 4653 if (!(id_cryptoctx->p11flags & C_LOGIN_DONE)) { 4654 CK_TOKEN_INFO tinfo; 4655 4656 r = id_cryptoctx->p11->C_GetTokenInfo(id_cryptoctx->slotid, &tinfo); 4657 if (r != 0) 4658 return r; 4659 4660 r = pkinit_login(context, id_cryptoctx, &tinfo); 4661 if (r != 0) 4662 return r; 4663 } 4664 4665 r = pkinit_find_private_key(id_cryptoctx, CKA_SIGN, &obj); 4666 if (r != 0 ) 4667 return r; 4668 4669 mech.mechanism = id_cryptoctx->mech; 4670 mech.pParameter = NULL; 4671 mech.ulParameterLen = 0; 4672 4673 if ((r = id_cryptoctx->p11->C_SignInit(id_cryptoctx->session, &mech, 4674 obj)) != CKR_OK) { 4675 pkiDebug("C_SignInit: %s\n", pkinit_pkcs11_code_to_text(r)); 4676 return KRB5KDC_ERR_PREAUTH_FAILED; 4677 } 4678 4679 /* 4680 * Key len would give an upper bound on sig size, but there's no way to 4681 * get that. So guess, and if it's too small, re-malloc. 4682 */ 4683 len = PK_SIGLEN_GUESS; 4684 cp = (unsigned char *)malloc((size_t) len); 4685 if (cp == NULL) 4686 return ENOMEM; 4687 4688 r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data, 4689 (CK_ULONG) data_len, cp, &len); 4690 if (r == CKR_BUFFER_TOO_SMALL || (r == CKR_OK && len >= PK_SIGLEN_GUESS)) { 4691 free(cp); 4692 pkiDebug("C_Sign realloc %d\n", (int) len); 4693 cp = (unsigned char *)malloc((size_t) len); 4694 r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data, 4695 (CK_ULONG) data_len, cp, &len); 4696 } 4697 if (r != CKR_OK) { 4698 pkiDebug("C_Sign: %s\n", pkinit_pkcs11_code_to_text(r)); 4699 return KRB5KDC_ERR_PREAUTH_FAILED; 4700 } 4701 pkiDebug("sign %d -> %d\n", (int) data_len, (int) len); 4702 *sig_len = len; 4703 *sig = cp; 4704 4705 return 0; 4706 } 4707 #endif 4708 4709 krb5_error_code 4710 pkinit_sign_data(krb5_context context, 4711 pkinit_identity_crypto_context id_cryptoctx, 4712 unsigned char *data, 4713 unsigned int data_len, 4714 unsigned char **sig, 4715 unsigned int *sig_len) 4716 { 4717 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; 4718 4719 if (id_cryptoctx == NULL || id_cryptoctx->pkcs11_method != 1) 4720 retval = pkinit_sign_data_fs(context, id_cryptoctx, data, data_len, 4721 sig, sig_len); 4722 #ifndef WITHOUT_PKCS11 4723 else 4724 retval = pkinit_sign_data_pkcs11(context, id_cryptoctx, data, data_len, 4725 sig, sig_len); 4726 #endif 4727 4728 return retval; 4729 } 4730 4731 4732 static krb5_error_code 4733 decode_data(unsigned char **out_data, unsigned int *out_data_len, 4734 unsigned char *data, unsigned int data_len, 4735 EVP_PKEY *pkey, X509 *cert) 4736 { 4737 /* Solaris Kerberos */ 4738 int len; 4739 unsigned char *buf = NULL; 4740 int buf_len = 0; 4741 4742 /* Solaris Kerberos */ 4743 if (out_data == NULL || out_data_len == NULL) 4744 return EINVAL; 4745 4746 if (cert && !X509_check_private_key(cert, pkey)) { 4747 pkiDebug("private key does not match certificate\n"); 4748 /* Solaris Kerberos */ 4749 return EINVAL; 4750 } 4751 4752 buf_len = EVP_PKEY_size(pkey); 4753 buf = (unsigned char *)malloc((size_t) buf_len + 10); 4754 if (buf == NULL) 4755 return ENOMEM; 4756 4757 #if OPENSSL_VERSION_NUMBER < 0x10000000L 4758 len = EVP_PKEY_decrypt(buf, data, (int)data_len, pkey); 4759 #else 4760 len = EVP_PKEY_decrypt_old(buf, data, (int)data_len, pkey); 4761 #endif 4762 if (len <= 0) { 4763 pkiDebug("unable to decrypt received data (len=%d)\n", data_len); 4764 /* Solaris Kerberos */ 4765 free(buf); 4766 return KRB5KRB_ERR_GENERIC; 4767 } 4768 *out_data = buf; 4769 *out_data_len = len; 4770 4771 return 0; 4772 } 4773 4774 static krb5_error_code 4775 create_signature(unsigned char **sig, unsigned int *sig_len, 4776 unsigned char *data, unsigned int data_len, EVP_PKEY *pkey) 4777 { 4778 krb5_error_code retval = ENOMEM; 4779 EVP_MD_CTX md_ctx; 4780 4781 if (pkey == NULL) 4782 /* Solaris Kerberos */ 4783 return EINVAL; 4784 4785 EVP_VerifyInit(&md_ctx, EVP_sha1()); 4786 EVP_SignUpdate(&md_ctx, data, data_len); 4787 *sig_len = EVP_PKEY_size(pkey); 4788 if ((*sig = (unsigned char *) malloc((size_t) *sig_len)) == NULL) 4789 goto cleanup; 4790 EVP_SignFinal(&md_ctx, *sig, sig_len, pkey); 4791 4792 retval = 0; 4793 4794 cleanup: 4795 EVP_MD_CTX_cleanup(&md_ctx); 4796 4797 return retval; 4798 } 4799 4800 /* 4801 * Note: 4802 * This is not the routine the KDC uses to get its certificate. 4803 * This routine is intended to be called by the client 4804 * to obtain the KDC's certificate from some local storage 4805 * to be sent as a hint in its request to the KDC. 4806 */ 4807 /* ARGSUSED */ 4808 krb5_error_code 4809 pkinit_get_kdc_cert(krb5_context context, 4810 pkinit_plg_crypto_context plg_cryptoctx, 4811 pkinit_req_crypto_context req_cryptoctx, 4812 pkinit_identity_crypto_context id_cryptoctx, 4813 krb5_principal princ) 4814 { 4815 /* Solaris Kerberos */ 4816 if (req_cryptoctx == NULL) 4817 return EINVAL; 4818 4819 req_cryptoctx->received_cert = NULL; 4820 return 0; 4821 } 4822 4823 /* ARGSUSED */ 4824 static krb5_error_code 4825 pkinit_get_certs_pkcs12(krb5_context context, 4826 pkinit_plg_crypto_context plg_cryptoctx, 4827 pkinit_req_crypto_context req_cryptoctx, 4828 pkinit_identity_opts *idopts, 4829 pkinit_identity_crypto_context id_cryptoctx, 4830 krb5_principal princ) 4831 { 4832 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; 4833 X509 *x = NULL; 4834 PKCS12 *p12 = NULL; 4835 int ret; 4836 FILE *fp; 4837 EVP_PKEY *y = NULL; 4838 4839 if (idopts->cert_filename == NULL) { 4840 /* Solaris Kerberos: Improved error messages */ 4841 krb5_set_error_message(context, retval, 4842 gettext("Failed to get certificate location")); 4843 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__); 4844 goto cleanup; 4845 } 4846 4847 if (idopts->key_filename == NULL) { 4848 /* Solaris Kerberos: Improved error messages */ 4849 krb5_set_error_message(context, retval, 4850 gettext("Failed to get private key location")); 4851 pkiDebug("%s: failed to get user's private key location\n", __FUNCTION__); 4852 goto cleanup; 4853 } 4854 4855 fp = fopen(idopts->cert_filename, "rb"); 4856 if (fp == NULL) { 4857 /* Solaris Kerberos: Improved error messages */ 4858 krb5_set_error_message(context, retval, 4859 gettext("Failed to open PKCS12 file '%s': %s"), 4860 idopts->cert_filename, error_message(errno)); 4861 pkiDebug("Failed to open PKCS12 file '%s', error %d\n", 4862 idopts->cert_filename, errno); 4863 goto cleanup; 4864 } 4865 4866 p12 = d2i_PKCS12_fp(fp, NULL); 4867 (void) fclose(fp); 4868 if (p12 == NULL) { 4869 krb5_set_error_message(context, retval, 4870 gettext("Failed to decode PKCS12 file '%s' contents"), 4871 idopts->cert_filename); 4872 pkiDebug("Failed to decode PKCS12 file '%s' contents\n", 4873 idopts->cert_filename); 4874 goto cleanup; 4875 } 4876 /* 4877 * Try parsing with no pass phrase first. If that fails, 4878 * prompt for the pass phrase and try again. 4879 */ 4880 ret = PKCS12_parse(p12, NULL, &y, &x, NULL); 4881 if (ret == 0) { 4882 krb5_data rdat; 4883 krb5_prompt kprompt; 4884 krb5_prompt_type prompt_type; 4885 int r = 0; 4886 char prompt_string[128]; 4887 char prompt_reply[128]; 4888 /* Solaris Kerberos */ 4889 char *prompt_prefix = gettext("Pass phrase for"); 4890 4891 pkiDebug("Initial PKCS12_parse with no password failed\n"); 4892 4893 if (id_cryptoctx->PIN != NULL) { 4894 /* Solaris Kerberos: use PIN if set */ 4895 rdat.data = id_cryptoctx->PIN; 4896 /* note rdat.length isn't needed in this case */ 4897 } else { 4898 (void) memset(prompt_reply, '\0', sizeof(prompt_reply)); 4899 rdat.data = prompt_reply; 4900 rdat.length = sizeof(prompt_reply); 4901 4902 r = snprintf(prompt_string, sizeof(prompt_string), "%s %s", 4903 prompt_prefix, idopts->cert_filename); 4904 if (r >= sizeof(prompt_string)) { 4905 pkiDebug("Prompt string, '%s %s', is too long!\n", 4906 prompt_prefix, idopts->cert_filename); 4907 goto cleanup; 4908 } 4909 kprompt.prompt = prompt_string; 4910 kprompt.hidden = 1; 4911 kprompt.reply = &rdat; 4912 prompt_type = KRB5_PROMPT_TYPE_PREAUTH; 4913 4914 /* PROMPTER_INVOCATION */ 4915 k5int_set_prompt_types(context, &prompt_type); 4916 r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data, 4917 NULL, NULL, 1, &kprompt); 4918 k5int_set_prompt_types(context, NULL); 4919 } 4920 4921 ret = PKCS12_parse(p12, rdat.data, &y, &x, NULL); 4922 if (ret == 0) { 4923 /* Solaris Kerberos: Improved error messages */ 4924 krb5_set_error_message(context, retval, 4925 gettext("Failed to parse PKCS12 file '%s' with password"), 4926 idopts->cert_filename); 4927 pkiDebug("Seconde PKCS12_parse with password failed\n"); 4928 goto cleanup; 4929 } 4930 } 4931 id_cryptoctx->creds[0] = malloc(sizeof(struct _pkinit_cred_info)); 4932 if (id_cryptoctx->creds[0] == NULL) 4933 goto cleanup; 4934 id_cryptoctx->creds[0]->cert = x; 4935 #ifndef WITHOUT_PKCS11 4936 id_cryptoctx->creds[0]->cert_id = NULL; 4937 id_cryptoctx->creds[0]->cert_id_len = 0; 4938 #endif 4939 id_cryptoctx->creds[0]->key = y; 4940 id_cryptoctx->creds[1] = NULL; 4941 4942 retval = 0; 4943 4944 cleanup: 4945 if (p12) 4946 PKCS12_free(p12); 4947 if (retval) { 4948 if (x != NULL) 4949 X509_free(x); 4950 if (y != NULL) 4951 EVP_PKEY_free(y); 4952 } 4953 return retval; 4954 } 4955 4956 static krb5_error_code 4957 pkinit_load_fs_cert_and_key(krb5_context context, 4958 pkinit_identity_crypto_context id_cryptoctx, 4959 char *certname, 4960 char *keyname, 4961 int cindex) 4962 { 4963 krb5_error_code retval; 4964 X509 *x = NULL; 4965 EVP_PKEY *y = NULL; 4966 4967 /* load the certificate */ 4968 retval = get_cert(certname, &x); 4969 if (retval != 0 || x == NULL) { 4970 /* Solaris Kerberos: Improved error messages */ 4971 krb5_set_error_message(context, retval, 4972 gettext("Failed to load user's certificate from %s: %s"), 4973 certname, error_message(retval)); 4974 pkiDebug("failed to load user's certificate from '%s'\n", certname); 4975 goto cleanup; 4976 } 4977 retval = get_key(keyname, &y); 4978 if (retval != 0 || y == NULL) { 4979 /* Solaris Kerberos: Improved error messages */ 4980 krb5_set_error_message(context, retval, 4981 gettext("Failed to load user's private key from %s: %s"), 4982 keyname, error_message(retval)); 4983 pkiDebug("failed to load user's private key from '%s'\n", keyname); 4984 goto cleanup; 4985 } 4986 4987 id_cryptoctx->creds[cindex] = malloc(sizeof(struct _pkinit_cred_info)); 4988 if (id_cryptoctx->creds[cindex] == NULL) { 4989 retval = ENOMEM; 4990 goto cleanup; 4991 } 4992 id_cryptoctx->creds[cindex]->cert = x; 4993 #ifndef WITHOUT_PKCS11 4994 id_cryptoctx->creds[cindex]->cert_id = NULL; 4995 id_cryptoctx->creds[cindex]->cert_id_len = 0; 4996 #endif 4997 id_cryptoctx->creds[cindex]->key = y; 4998 id_cryptoctx->creds[cindex+1] = NULL; 4999 5000 retval = 0; 5001 5002 cleanup: 5003 if (retval) { 5004 if (x != NULL) 5005 X509_free(x); 5006 if (y != NULL) 5007 EVP_PKEY_free(y); 5008 } 5009 return retval; 5010 } 5011 5012 /* ARGSUSED */ 5013 static krb5_error_code 5014 pkinit_get_certs_fs(krb5_context context, 5015 pkinit_plg_crypto_context plg_cryptoctx, 5016 pkinit_req_crypto_context req_cryptoctx, 5017 pkinit_identity_opts *idopts, 5018 pkinit_identity_crypto_context id_cryptoctx, 5019 krb5_principal princ) 5020 { 5021 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; 5022 5023 if (idopts->cert_filename == NULL) { 5024 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__); 5025 goto cleanup; 5026 } 5027 5028 if (idopts->key_filename == NULL) { 5029 pkiDebug("%s: failed to get user's private key location\n", 5030 __FUNCTION__); 5031 goto cleanup; 5032 } 5033 5034 retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx, 5035 idopts->cert_filename, 5036 idopts->key_filename, 0); 5037 cleanup: 5038 return retval; 5039 } 5040 5041 /* ARGSUSED */ 5042 static krb5_error_code 5043 pkinit_get_certs_dir(krb5_context context, 5044 pkinit_plg_crypto_context plg_cryptoctx, 5045 pkinit_req_crypto_context req_cryptoctx, 5046 pkinit_identity_opts *idopts, 5047 pkinit_identity_crypto_context id_cryptoctx, 5048 krb5_principal princ) 5049 { 5050 /* Solaris Kerberos */ 5051 krb5_error_code retval = KRB5KRB_ERR_GENERIC; 5052 DIR *d = NULL; 5053 struct dirent *dentry = NULL; 5054 char certname[1024]; 5055 char keyname[1024]; 5056 int i = 0, len; 5057 char *dirname, *suf; 5058 5059 /* Solaris Kerberos */ 5060 if (idopts == NULL) 5061 return EINVAL; 5062 5063 if (idopts->cert_filename == NULL) { 5064 pkiDebug("%s: failed to get user's certificate directory location\n", 5065 __FUNCTION__); 5066 return ENOENT; 5067 } 5068 5069 dirname = idopts->cert_filename; 5070 d = opendir(dirname); 5071 if (d == NULL) { 5072 /* Solaris Kerberos: Improved error messages */ 5073 krb5_set_error_message(context, errno, 5074 gettext("Failed to open directory \"%s\": %s"), 5075 dirname, error_message(errno)); 5076 return errno; 5077 } 5078 5079 /* 5080 * We'll assume that certs are named XXX.crt and the corresponding 5081 * key is named XXX.key 5082 */ 5083 while ((i < MAX_CREDS_ALLOWED) && (dentry = readdir(d)) != NULL) { 5084 /* Ignore subdirectories and anything starting with a dot */ 5085 #ifdef DT_DIR 5086 if (dentry->d_type == DT_DIR) 5087 continue; 5088 #endif 5089 if (dentry->d_name[0] == '.') 5090 continue; 5091 len = strlen(dentry->d_name); 5092 if (len < 5) 5093 continue; 5094 suf = dentry->d_name + (len - 4); 5095 if (strncmp(suf, ".crt", 4) != 0) 5096 continue; 5097 5098 /* Checked length */ 5099 if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(certname)) { 5100 pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n", 5101 __FUNCTION__, dirname, dentry->d_name); 5102 continue; 5103 } 5104 (void) snprintf(certname, sizeof(certname), "%s/%s", dirname, dentry->d_name); 5105 (void) snprintf(keyname, sizeof(keyname), "%s/%s", dirname, dentry->d_name); 5106 len = strlen(keyname); 5107 keyname[len - 3] = 'k'; 5108 keyname[len - 2] = 'e'; 5109 keyname[len - 1] = 'y'; 5110 5111 retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx, 5112 certname, keyname, i); 5113 if (retval == 0) { 5114 pkiDebug("%s: Successfully loaded cert (and key) for %s\n", 5115 __FUNCTION__, dentry->d_name); 5116 i++; 5117 } 5118 else 5119 continue; 5120 } 5121 5122 if (i == 0) { 5123 /* Solaris Kerberos: Improved error messages */ 5124 krb5_set_error_message(context, ENOENT, 5125 gettext("No suitable cert/key pairs found in directory '%s'"), 5126 idopts->cert_filename); 5127 pkiDebug("%s: No cert/key pairs found in directory '%s'\n", 5128 __FUNCTION__, idopts->cert_filename); 5129 retval = ENOENT; 5130 goto cleanup; 5131 } 5132 5133 retval = 0; 5134 5135 cleanup: 5136 if (d) 5137 (void) closedir(d); 5138 5139 return retval; 5140 } 5141 5142 #ifndef WITHOUT_PKCS11 5143 /* ARGSUSED */ 5144 static krb5_error_code 5145 pkinit_get_certs_pkcs11(krb5_context context, 5146 pkinit_plg_crypto_context plg_cryptoctx, 5147 pkinit_req_crypto_context req_cryptoctx, 5148 pkinit_identity_opts *idopts, 5149 pkinit_identity_crypto_context id_cryptoctx, 5150 krb5_principal princ, 5151 int do_matching) 5152 { 5153 #ifdef PKINIT_USE_MECH_LIST 5154 CK_MECHANISM_TYPE_PTR mechp = NULL; 5155 CK_MECHANISM_INFO info; 5156 #endif 5157 5158 if (id_cryptoctx->p11flags & C_SKIP_PKCS11_AUTH) 5159 return KRB5KDC_ERR_PREAUTH_FAILED; 5160 5161 /* Copy stuff from idopts -> id_cryptoctx */ 5162 if (idopts->p11_module_name != NULL) { 5163 id_cryptoctx->p11_module_name = strdup(idopts->p11_module_name); 5164 if (id_cryptoctx->p11_module_name == NULL) 5165 return ENOMEM; 5166 } 5167 if (idopts->token_label != NULL) { 5168 id_cryptoctx->token_label = strdup(idopts->token_label); 5169 if (id_cryptoctx->token_label == NULL) 5170 return ENOMEM; 5171 } 5172 if (idopts->cert_label != NULL) { 5173 id_cryptoctx->cert_label = strdup(idopts->cert_label); 5174 if (id_cryptoctx->cert_label == NULL) 5175 return ENOMEM; 5176 } 5177 if (idopts->PIN != NULL) { 5178 id_cryptoctx->PIN = strdup(idopts->PIN); 5179 if (id_cryptoctx->PIN == NULL) 5180 return ENOMEM; 5181 } 5182 /* Convert the ascii cert_id string into a binary blob */ 5183 /* 5184 * Solaris Kerberos: 5185 * If the cert_id_string is empty then behave in a similar way to how 5186 * an empty certlabel is treated - i.e. don't fail now but rather continue 5187 * as though the certid wasn't specified. 5188 */ 5189 if (idopts->cert_id_string != NULL && strlen(idopts->cert_id_string) != 0) { 5190 BIGNUM *bn = NULL; 5191 BN_hex2bn(&bn, idopts->cert_id_string); 5192 if (bn == NULL) 5193 return ENOMEM; 5194 id_cryptoctx->cert_id_len = BN_num_bytes(bn); 5195 id_cryptoctx->cert_id = malloc((size_t) id_cryptoctx->cert_id_len); 5196 if (id_cryptoctx->cert_id == NULL) { 5197 BN_free(bn); 5198 return ENOMEM; 5199 } 5200 BN_bn2bin(bn, id_cryptoctx->cert_id); 5201 BN_free(bn); 5202 } 5203 id_cryptoctx->slotid = idopts->slotid; 5204 id_cryptoctx->pkcs11_method = 1; 5205 5206 #ifndef PKINIT_USE_MECH_LIST 5207 /* 5208 * We'd like to use CKM_SHA1_RSA_PKCS for signing if it's available, but 5209 * many cards seems to be confused about whether they are capable of 5210 * this or not. The safe thing seems to be to ignore the mechanism list, 5211 * always use CKM_RSA_PKCS and calculate the sha1 digest ourselves. 5212 */ 5213 5214 id_cryptoctx->mech = CKM_RSA_PKCS; 5215 #else 5216 if ((r = id_cryptoctx->p11->C_GetMechanismList(id_cryptoctx->slotid, NULL, 5217 &count)) != CKR_OK || count <= 0) { 5218 pkiDebug("C_GetMechanismList: %s\n", pkinit_pkcs11_code_to_text(r)); 5219 return KRB5KDC_ERR_PREAUTH_FAILED; 5220 } 5221 mechp = (CK_MECHANISM_TYPE_PTR) malloc(count * sizeof (CK_MECHANISM_TYPE)); 5222 if (mechp == NULL) 5223 return ENOMEM; 5224 if ((r = id_cryptoctx->p11->C_GetMechanismList(id_cryptoctx->slotid, 5225 mechp, &count)) != CKR_OK) { 5226 free(mechp); 5227 return KRB5KDC_ERR_PREAUTH_FAILED; 5228 } 5229 for (i = 0; i < count; i++) { 5230 if ((r = id_cryptoctx->p11->C_GetMechanismInfo(id_cryptoctx->slotid, 5231 mechp[i], &info)) != CKR_OK) { 5232 free(mechp); 5233 return KRB5KDC_ERR_PREAUTH_FAILED; 5234 } 5235 #ifdef DEBUG_MECHINFO 5236 pkiDebug("mech %x flags %x\n", (int) mechp[i], (int) info.flags); 5237 if ((info.flags & (CKF_SIGN|CKF_DECRYPT)) == (CKF_SIGN|CKF_DECRYPT)) 5238 pkiDebug(" this mech is good for sign & decrypt\n"); 5239 #endif 5240 if (mechp[i] == CKM_RSA_PKCS) { 5241 /* This seems backwards... */ 5242 id_cryptoctx->mech = 5243 (info.flags & CKF_SIGN) ? CKM_SHA1_RSA_PKCS : CKM_RSA_PKCS; 5244 } 5245 } 5246 free(mechp); 5247 5248 pkiDebug("got %d mechs from card\n", (int) count); 5249 #endif 5250 5251 return (pkinit_open_session(context, plg_cryptoctx, req_cryptoctx, 5252 id_cryptoctx, princ, do_matching)); 5253 } 5254 #endif 5255 5256 /* ARGSUSED */ 5257 static void 5258 free_cred_info(krb5_context context, 5259 pkinit_identity_crypto_context id_cryptoctx, 5260 struct _pkinit_cred_info *cred) 5261 { 5262 if (cred != NULL) { 5263 if (cred->cert != NULL) 5264 X509_free(cred->cert); 5265 if (cred->key != NULL) 5266 EVP_PKEY_free(cred->key); 5267 #ifndef WITHOUT_PKCS11 5268 if (cred->cert_id != NULL) 5269 free(cred->cert_id); 5270 #endif 5271 free(cred); 5272 } 5273 } 5274 5275 /* ARGSUSED */ 5276 krb5_error_code 5277 crypto_free_cert_info(krb5_context context, 5278 pkinit_plg_crypto_context plg_cryptoctx, 5279 pkinit_req_crypto_context req_cryptoctx, 5280 pkinit_identity_crypto_context id_cryptoctx) 5281 { 5282 int i; 5283 5284 if (id_cryptoctx == NULL) 5285 return EINVAL; 5286 5287 for (i = 0; i < MAX_CREDS_ALLOWED; i++) { 5288 if (id_cryptoctx->creds[i] != NULL) { 5289 free_cred_info(context, id_cryptoctx, id_cryptoctx->creds[i]); 5290 id_cryptoctx->creds[i] = NULL; 5291 } 5292 } 5293 return 0; 5294 } 5295 5296 krb5_error_code 5297 crypto_load_certs(krb5_context context, 5298 pkinit_plg_crypto_context plg_cryptoctx, 5299 pkinit_req_crypto_context req_cryptoctx, 5300 pkinit_identity_opts *idopts, 5301 pkinit_identity_crypto_context id_cryptoctx, 5302 krb5_principal princ, 5303 int do_matching) 5304 { 5305 krb5_error_code retval; 5306 5307 switch(idopts->idtype) { 5308 case IDTYPE_FILE: 5309 retval = pkinit_get_certs_fs(context, plg_cryptoctx, 5310 req_cryptoctx, idopts, 5311 id_cryptoctx, princ); 5312 break; 5313 case IDTYPE_DIR: 5314 retval = pkinit_get_certs_dir(context, plg_cryptoctx, 5315 req_cryptoctx, idopts, 5316 id_cryptoctx, princ); 5317 break; 5318 #ifndef WITHOUT_PKCS11 5319 case IDTYPE_PKCS11: 5320 retval = pkinit_get_certs_pkcs11(context, plg_cryptoctx, 5321 req_cryptoctx, idopts, 5322 id_cryptoctx, princ, do_matching); 5323 break; 5324 #endif 5325 case IDTYPE_PKCS12: 5326 retval = pkinit_get_certs_pkcs12(context, plg_cryptoctx, 5327 req_cryptoctx, idopts, 5328 id_cryptoctx, princ); 5329 break; 5330 default: 5331 retval = EINVAL; 5332 } 5333 /* Solaris Kerberos */ 5334 5335 return retval; 5336 } 5337 5338 /* 5339 * Get number of certificates available after crypto_load_certs() 5340 */ 5341 /* ARGSUSED */ 5342 krb5_error_code 5343 crypto_cert_get_count(krb5_context context, 5344 pkinit_plg_crypto_context plg_cryptoctx, 5345 pkinit_req_crypto_context req_cryptoctx, 5346 pkinit_identity_crypto_context id_cryptoctx, 5347 int *cert_count) 5348 { 5349 int count; 5350 5351 if (id_cryptoctx == NULL || id_cryptoctx->creds[0] == NULL) 5352 return EINVAL; 5353 5354 for (count = 0; 5355 count <= MAX_CREDS_ALLOWED && id_cryptoctx->creds[count] != NULL; 5356 count++); 5357 *cert_count = count; 5358 return 0; 5359 } 5360 5361 5362 /* 5363 * Begin iteration over the certs loaded in crypto_load_certs() 5364 */ 5365 /* ARGSUSED */ 5366 krb5_error_code 5367 crypto_cert_iteration_begin(krb5_context context, 5368 pkinit_plg_crypto_context plg_cryptoctx, 5369 pkinit_req_crypto_context req_cryptoctx, 5370 pkinit_identity_crypto_context id_cryptoctx, 5371 pkinit_cert_iter_handle *ih_ret) 5372 { 5373 struct _pkinit_cert_iter_data *id; 5374 5375 if (id_cryptoctx == NULL || ih_ret == NULL) 5376 return EINVAL; 5377 if (id_cryptoctx->creds[0] == NULL) /* No cred info available */ 5378 return ENOENT; 5379 5380 id = calloc(1, sizeof(*id)); 5381 if (id == NULL) 5382 return ENOMEM; 5383 id->magic = ITER_MAGIC; 5384 id->plgctx = plg_cryptoctx, 5385 id->reqctx = req_cryptoctx, 5386 id->idctx = id_cryptoctx; 5387 id->index = 0; 5388 *ih_ret = (pkinit_cert_iter_handle) id; 5389 return 0; 5390 } 5391 5392 /* 5393 * End iteration over the certs loaded in crypto_load_certs() 5394 */ 5395 /* ARGSUSED */ 5396 krb5_error_code 5397 crypto_cert_iteration_end(krb5_context context, 5398 pkinit_cert_iter_handle ih) 5399 { 5400 struct _pkinit_cert_iter_data *id = (struct _pkinit_cert_iter_data *)ih; 5401 5402 if (id == NULL || id->magic != ITER_MAGIC) 5403 return EINVAL; 5404 free(ih); 5405 return 0; 5406 } 5407 5408 /* 5409 * Get next certificate handle 5410 */ 5411 /* ARGSUSED */ 5412 krb5_error_code 5413 crypto_cert_iteration_next(krb5_context context, 5414 pkinit_cert_iter_handle ih, 5415 pkinit_cert_handle *ch_ret) 5416 { 5417 struct _pkinit_cert_iter_data *id = (struct _pkinit_cert_iter_data *)ih; 5418 struct _pkinit_cert_data *cd; 5419 pkinit_identity_crypto_context id_cryptoctx; 5420 5421 if (id == NULL || id->magic != ITER_MAGIC) 5422 return EINVAL; 5423 5424 if (ch_ret == NULL) 5425 return EINVAL; 5426 5427 id_cryptoctx = id->idctx; 5428 if (id_cryptoctx == NULL) 5429 return EINVAL; 5430 5431 if (id_cryptoctx->creds[id->index] == NULL) 5432 return PKINIT_ITER_NO_MORE; 5433 5434 cd = calloc(1, sizeof(*cd)); 5435 if (cd == NULL) 5436 return ENOMEM; 5437 5438 cd->magic = CERT_MAGIC; 5439 cd->plgctx = id->plgctx; 5440 cd->reqctx = id->reqctx; 5441 cd->idctx = id->idctx; 5442 cd->index = id->index; 5443 cd->cred = id_cryptoctx->creds[id->index++]; 5444 *ch_ret = (pkinit_cert_handle)cd; 5445 return 0; 5446 } 5447 5448 /* 5449 * Release cert handle 5450 */ 5451 /* ARGSUSED */ 5452 krb5_error_code 5453 crypto_cert_release(krb5_context context, 5454 pkinit_cert_handle ch) 5455 { 5456 struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch; 5457 if (cd == NULL || cd->magic != CERT_MAGIC) 5458 return EINVAL; 5459 free(cd); 5460 return 0; 5461 } 5462 5463 /* 5464 * Get certificate Key Usage and Extended Key Usage 5465 */ 5466 /* ARGSUSED */ 5467 static krb5_error_code 5468 crypto_retieve_X509_key_usage(krb5_context context, 5469 pkinit_plg_crypto_context plgcctx, 5470 pkinit_req_crypto_context reqcctx, 5471 X509 *x, 5472 unsigned int *ret_ku_bits, 5473 unsigned int *ret_eku_bits) 5474 { 5475 /* Solaris Kerberos */ 5476 int i; 5477 unsigned int eku_bits = 0, ku_bits = 0; 5478 ASN1_BIT_STRING *usage = NULL; 5479 5480 if (ret_ku_bits == NULL && ret_eku_bits == NULL) 5481 return EINVAL; 5482 5483 if (ret_eku_bits) 5484 *ret_eku_bits = 0; 5485 else { 5486 pkiDebug("%s: EKUs not requested, not checking\n", __FUNCTION__); 5487 goto check_kus; 5488 } 5489 5490 /* Start with Extended Key usage */ 5491 i = X509_get_ext_by_NID(x, NID_ext_key_usage, -1); 5492 if (i >= 0) { 5493 EXTENDED_KEY_USAGE *eku; 5494 5495 eku = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL); 5496 if (eku) { 5497 for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) { 5498 ASN1_OBJECT *certoid; 5499 certoid = sk_ASN1_OBJECT_value(eku, i); 5500 if ((OBJ_cmp(certoid, plgcctx->id_pkinit_KPClientAuth)) == 0) 5501 eku_bits |= PKINIT_EKU_PKINIT; 5502 else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_ms_smartcard_login))) == 0) 5503 eku_bits |= PKINIT_EKU_MSSCLOGIN; 5504 else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_client_auth))) == 0) 5505 eku_bits |= PKINIT_EKU_CLIENTAUTH; 5506 else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_email_protect))) == 0) 5507 eku_bits |= PKINIT_EKU_EMAILPROTECTION; 5508 } 5509 EXTENDED_KEY_USAGE_free(eku); 5510 } 5511 } 5512 pkiDebug("%s: returning eku 0x%08x\n", __FUNCTION__, eku_bits); 5513 *ret_eku_bits = eku_bits; 5514 5515 check_kus: 5516 /* Now the Key Usage bits */ 5517 if (ret_ku_bits) 5518 *ret_ku_bits = 0; 5519 else { 5520 pkiDebug("%s: KUs not requested, not checking\n", __FUNCTION__); 5521 goto out; 5522 } 5523 5524 /* Make sure usage exists before checking bits */ 5525 usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL); 5526 if (usage) { 5527 if (!ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE)) 5528 ku_bits |= PKINIT_KU_DIGITALSIGNATURE; 5529 if (!ku_reject(x, X509v3_KU_KEY_ENCIPHERMENT)) 5530 ku_bits |= PKINIT_KU_KEYENCIPHERMENT; 5531 ASN1_BIT_STRING_free(usage); 5532 } 5533 5534 pkiDebug("%s: returning ku 0x%08x\n", __FUNCTION__, ku_bits); 5535 *ret_ku_bits = ku_bits; 5536 5537 out: 5538 return 0; 5539 } 5540 5541 /* 5542 * Return a string format of an X509_NAME in buf where 5543 * size is an in/out parameter. On input it is the size 5544 * of the buffer, and on output it is the actual length 5545 * of the name. 5546 * If buf is NULL, returns the length req'd to hold name 5547 */ 5548 static char * 5549 X509_NAME_oneline_ex(X509_NAME * a, 5550 char *buf, 5551 unsigned int *size, 5552 unsigned long flag) 5553 { 5554 BIO *out = NULL; 5555 5556 out = BIO_new(BIO_s_mem ()); 5557 if (X509_NAME_print_ex(out, a, 0, flag) > 0) { 5558 if (buf != NULL && *size > (int) BIO_number_written(out)) { 5559 (void) memset(buf, 0, *size); 5560 BIO_read(out, buf, (int) BIO_number_written(out)); 5561 } 5562 else { 5563 *size = BIO_number_written(out); 5564 } 5565 } 5566 BIO_free(out); 5567 return (buf); 5568 } 5569 5570 /* 5571 * Get certificate information 5572 */ 5573 krb5_error_code 5574 crypto_cert_get_matching_data(krb5_context context, 5575 pkinit_cert_handle ch, 5576 pkinit_cert_matching_data **ret_md) 5577 { 5578 krb5_error_code retval; 5579 pkinit_cert_matching_data *md; 5580 krb5_principal *pkinit_sans =NULL, *upn_sans = NULL; 5581 struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch; 5582 int i, j; 5583 char buf[DN_BUF_LEN]; 5584 unsigned int bufsize = sizeof(buf); 5585 5586 if (cd == NULL || cd->magic != CERT_MAGIC) 5587 return EINVAL; 5588 if (ret_md == NULL) 5589 return EINVAL; 5590 5591 md = calloc(1, sizeof(*md)); 5592 if (md == NULL) 5593 return ENOMEM; 5594 5595 md->ch = ch; 5596 5597 /* get the subject name (in rfc2253 format) */ 5598 X509_NAME_oneline_ex(X509_get_subject_name(cd->cred->cert), 5599 buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS); 5600 md->subject_dn = strdup(buf); 5601 if (md->subject_dn == NULL) { 5602 retval = ENOMEM; 5603 goto cleanup; 5604 } 5605 5606 /* get the issuer name (in rfc2253 format) */ 5607 X509_NAME_oneline_ex(X509_get_issuer_name(cd->cred->cert), 5608 buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS); 5609 md->issuer_dn = strdup(buf); 5610 if (md->issuer_dn == NULL) { 5611 retval = ENOMEM; 5612 goto cleanup; 5613 } 5614 5615 /* get the san data */ 5616 retval = crypto_retrieve_X509_sans(context, cd->plgctx, cd->reqctx, 5617 cd->cred->cert, &pkinit_sans, 5618 &upn_sans, NULL); 5619 if (retval) 5620 goto cleanup; 5621 5622 j = 0; 5623 if (pkinit_sans != NULL) { 5624 for (i = 0; pkinit_sans[i] != NULL; i++) 5625 j++; 5626 } 5627 if (upn_sans != NULL) { 5628 for (i = 0; upn_sans[i] != NULL; i++) 5629 j++; 5630 } 5631 if (j != 0) { 5632 md->sans = calloc((size_t)j+1, sizeof(*md->sans)); 5633 if (md->sans == NULL) { 5634 retval = ENOMEM; 5635 goto cleanup; 5636 } 5637 j = 0; 5638 if (pkinit_sans != NULL) { 5639 for (i = 0; pkinit_sans[i] != NULL; i++) 5640 md->sans[j++] = pkinit_sans[i]; 5641 free(pkinit_sans); 5642 } 5643 if (upn_sans != NULL) { 5644 for (i = 0; upn_sans[i] != NULL; i++) 5645 md->sans[j++] = upn_sans[i]; 5646 free(upn_sans); 5647 } 5648 md->sans[j] = NULL; 5649 } else 5650 md->sans = NULL; 5651 5652 /* get the KU and EKU data */ 5653 5654 retval = crypto_retieve_X509_key_usage(context, cd->plgctx, cd->reqctx, 5655 cd->cred->cert, 5656 &md->ku_bits, &md->eku_bits); 5657 if (retval) 5658 goto cleanup; 5659 5660 *ret_md = md; 5661 retval = 0; 5662 cleanup: 5663 if (retval) { 5664 if (md) 5665 crypto_cert_free_matching_data(context, md); 5666 } 5667 return retval; 5668 } 5669 5670 /* 5671 * Free certificate information 5672 */ 5673 krb5_error_code 5674 crypto_cert_free_matching_data(krb5_context context, 5675 pkinit_cert_matching_data *md) 5676 { 5677 krb5_principal p; 5678 int i; 5679 5680 if (md == NULL) 5681 return EINVAL; 5682 if (md->subject_dn) 5683 free(md->subject_dn); 5684 if (md->issuer_dn) 5685 free(md->issuer_dn); 5686 if (md->sans) { 5687 for (i = 0, p = md->sans[i]; p != NULL; p = md->sans[++i]) 5688 krb5_free_principal(context, p); 5689 free(md->sans); 5690 } 5691 free(md); 5692 return 0; 5693 } 5694 5695 /* 5696 * Make this matching certificate "the chosen one" 5697 */ 5698 /* ARGSUSED */ 5699 krb5_error_code 5700 crypto_cert_select(krb5_context context, 5701 pkinit_cert_matching_data *md) 5702 { 5703 struct _pkinit_cert_data *cd; 5704 if (md == NULL) 5705 return EINVAL; 5706 5707 cd = (struct _pkinit_cert_data *)md->ch; 5708 if (cd == NULL || cd->magic != CERT_MAGIC) 5709 return EINVAL; 5710 5711 /* copy the selected cert into our id_cryptoctx */ 5712 if (cd->idctx->my_certs != NULL) { 5713 sk_X509_pop_free(cd->idctx->my_certs, X509_free); 5714 } 5715 cd->idctx->my_certs = sk_X509_new_null(); 5716 sk_X509_push(cd->idctx->my_certs, cd->cred->cert); 5717 cd->idctx->creds[cd->index]->cert = NULL; /* Don't free it twice */ 5718 cd->idctx->cert_index = 0; 5719 5720 if (cd->idctx->pkcs11_method != 1) { 5721 cd->idctx->my_key = cd->cred->key; 5722 cd->idctx->creds[cd->index]->key = NULL; /* Don't free it twice */ 5723 } 5724 #ifndef WITHOUT_PKCS11 5725 else { 5726 cd->idctx->cert_id = cd->cred->cert_id; 5727 cd->idctx->creds[cd->index]->cert_id = NULL; /* Don't free it twice */ 5728 cd->idctx->cert_id_len = cd->cred->cert_id_len; 5729 } 5730 #endif 5731 return 0; 5732 } 5733 5734 /* 5735 * Choose the default certificate as "the chosen one" 5736 */ 5737 krb5_error_code 5738 crypto_cert_select_default(krb5_context context, 5739 pkinit_plg_crypto_context plg_cryptoctx, 5740 pkinit_req_crypto_context req_cryptoctx, 5741 pkinit_identity_crypto_context id_cryptoctx) 5742 { 5743 krb5_error_code retval; 5744 int cert_count = 0; 5745 5746 retval = crypto_cert_get_count(context, plg_cryptoctx, req_cryptoctx, 5747 id_cryptoctx, &cert_count); 5748 if (retval) { 5749 pkiDebug("%s: crypto_cert_get_count error %d, %s\n", 5750 __FUNCTION__, retval, error_message(retval)); 5751 goto errout; 5752 } 5753 if (cert_count != 1) { 5754 /* Solaris Kerberos: Improved error messages */ 5755 retval = EINVAL; 5756 krb5_set_error_message(context, retval, 5757 gettext("Failed to select default certificate: " 5758 "found %d certs to choose from but there must be exactly one"), 5759 cert_count); 5760 pkiDebug("%s: ERROR: There are %d certs to choose from, " 5761 "but there must be exactly one.\n", 5762 __FUNCTION__, cert_count); 5763 goto errout; 5764 } 5765 /* copy the selected cert into our id_cryptoctx */ 5766 if (id_cryptoctx->my_certs != NULL) { 5767 sk_X509_pop_free(id_cryptoctx->my_certs, X509_free); 5768 } 5769 id_cryptoctx->my_certs = sk_X509_new_null(); 5770 sk_X509_push(id_cryptoctx->my_certs, id_cryptoctx->creds[0]->cert); 5771 id_cryptoctx->creds[0]->cert = NULL; /* Don't free it twice */ 5772 id_cryptoctx->cert_index = 0; 5773 5774 if (id_cryptoctx->pkcs11_method != 1) { 5775 id_cryptoctx->my_key = id_cryptoctx->creds[0]->key; 5776 id_cryptoctx->creds[0]->key = NULL; /* Don't free it twice */ 5777 } 5778 #ifndef WITHOUT_PKCS11 5779 else { 5780 id_cryptoctx->cert_id = id_cryptoctx->creds[0]->cert_id; 5781 id_cryptoctx->creds[0]->cert_id = NULL; /* Don't free it twice */ 5782 id_cryptoctx->cert_id_len = id_cryptoctx->creds[0]->cert_id_len; 5783 } 5784 #endif 5785 retval = 0; 5786 errout: 5787 return retval; 5788 } 5789 5790 5791 /* ARGSUSED */ 5792 static krb5_error_code 5793 load_cas_and_crls(krb5_context context, 5794 pkinit_plg_crypto_context plg_cryptoctx, 5795 pkinit_req_crypto_context req_cryptoctx, 5796 pkinit_identity_crypto_context id_cryptoctx, 5797 int catype, 5798 char *filename) 5799 { 5800 STACK_OF(X509_INFO) *sk = NULL; 5801 STACK_OF(X509) *ca_certs = NULL; 5802 STACK_OF(X509_CRL) *ca_crls = NULL; 5803 BIO *in = NULL; 5804 /* Solaris Kerberos */ 5805 krb5_error_code retval = KRB5KRB_ERR_GENERIC; 5806 int i = 0; 5807 5808 /* If there isn't already a stack in the context, 5809 * create a temporary one now */ 5810 switch(catype) { 5811 case CATYPE_ANCHORS: 5812 if (id_cryptoctx->trustedCAs != NULL) 5813 ca_certs = id_cryptoctx->trustedCAs; 5814 else { 5815 ca_certs = sk_X509_new_null(); 5816 if (ca_certs == NULL) 5817 return ENOMEM; 5818 } 5819 break; 5820 case CATYPE_INTERMEDIATES: 5821 if (id_cryptoctx->intermediateCAs != NULL) 5822 ca_certs = id_cryptoctx->intermediateCAs; 5823 else { 5824 ca_certs = sk_X509_new_null(); 5825 if (ca_certs == NULL) 5826 return ENOMEM; 5827 } 5828 break; 5829 case CATYPE_CRLS: 5830 if (id_cryptoctx->revoked != NULL) 5831 ca_crls = id_cryptoctx->revoked; 5832 else { 5833 ca_crls = sk_X509_CRL_new_null(); 5834 if (ca_crls == NULL) 5835 return ENOMEM; 5836 } 5837 break; 5838 default: 5839 return ENOTSUP; 5840 } 5841 5842 if (!(in = BIO_new_file(filename, "r"))) { 5843 retval = errno; 5844 pkiDebug("%s: error opening file '%s': %s\n", __FUNCTION__, 5845 filename, error_message(errno)); 5846 goto cleanup; 5847 } 5848 5849 /* This loads from a file, a stack of x509/crl/pkey sets */ 5850 if ((sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL)) == NULL) { 5851 pkiDebug("%s: error reading file '%s'\n", __FUNCTION__, filename); 5852 retval = EIO; 5853 goto cleanup; 5854 } 5855 5856 /* scan over the stack created from loading the file contents, 5857 * weed out duplicates, and push new ones onto the return stack 5858 */ 5859 for (i = 0; i < sk_X509_INFO_num(sk); i++) { 5860 X509_INFO *xi = sk_X509_INFO_value(sk, i); 5861 if (xi != NULL && xi->x509 != NULL && catype != CATYPE_CRLS) { 5862 int j = 0, size = sk_X509_num(ca_certs), flag = 0; 5863 5864 if (!size) { 5865 sk_X509_push(ca_certs, xi->x509); 5866 xi->x509 = NULL; 5867 continue; 5868 } 5869 for (j = 0; j < size; j++) { 5870 X509 *x = sk_X509_value(ca_certs, j); 5871 flag = X509_cmp(x, xi->x509); 5872 if (flag == 0) 5873 break; 5874 else 5875 continue; 5876 } 5877 if (flag != 0) { 5878 sk_X509_push(ca_certs, X509_dup(xi->x509)); 5879 } 5880 } else if (xi != NULL && xi->crl != NULL && catype == CATYPE_CRLS) { 5881 int j = 0, size = sk_X509_CRL_num(ca_crls), flag = 0; 5882 if (!size) { 5883 sk_X509_CRL_push(ca_crls, xi->crl); 5884 xi->crl = NULL; 5885 continue; 5886 } 5887 for (j = 0; j < size; j++) { 5888 X509_CRL *x = sk_X509_CRL_value(ca_crls, j); 5889 flag = X509_CRL_cmp(x, xi->crl); 5890 if (flag == 0) 5891 break; 5892 else 5893 continue; 5894 } 5895 if (flag != 0) { 5896 sk_X509_CRL_push(ca_crls, X509_CRL_dup(xi->crl)); 5897 } 5898 } 5899 } 5900 5901 /* If we added something and there wasn't a stack in the 5902 * context before, add the temporary stack to the context. 5903 */ 5904 switch(catype) { 5905 case CATYPE_ANCHORS: 5906 if (sk_X509_num(ca_certs) == 0) { 5907 pkiDebug("no anchors in file, %s\n", filename); 5908 if (id_cryptoctx->trustedCAs == NULL) 5909 sk_X509_free(ca_certs); 5910 } else { 5911 if (id_cryptoctx->trustedCAs == NULL) 5912 id_cryptoctx->trustedCAs = ca_certs; 5913 } 5914 break; 5915 case CATYPE_INTERMEDIATES: 5916 if (sk_X509_num(ca_certs) == 0) { 5917 pkiDebug("no intermediates in file, %s\n", filename); 5918 if (id_cryptoctx->intermediateCAs == NULL) 5919 sk_X509_free(ca_certs); 5920 } else { 5921 if (id_cryptoctx->intermediateCAs == NULL) 5922 id_cryptoctx->intermediateCAs = ca_certs; 5923 } 5924 break; 5925 case CATYPE_CRLS: 5926 if (sk_X509_CRL_num(ca_crls) == 0) { 5927 pkiDebug("no crls in file, %s\n", filename); 5928 if (id_cryptoctx->revoked == NULL) 5929 sk_X509_CRL_free(ca_crls); 5930 } else { 5931 if (id_cryptoctx->revoked == NULL) 5932 id_cryptoctx->revoked = ca_crls; 5933 } 5934 break; 5935 default: 5936 /* Should have been caught above! */ 5937 retval = EINVAL; 5938 goto cleanup; 5939 /* Solaris Kerberos: removed "break" as it's never reached */ 5940 } 5941 5942 retval = 0; 5943 5944 cleanup: 5945 if (in != NULL) 5946 BIO_free(in); 5947 if (sk != NULL) 5948 sk_X509_INFO_pop_free(sk, X509_INFO_free); 5949 5950 return retval; 5951 } 5952 5953 static krb5_error_code 5954 load_cas_and_crls_dir(krb5_context context, 5955 pkinit_plg_crypto_context plg_cryptoctx, 5956 pkinit_req_crypto_context req_cryptoctx, 5957 pkinit_identity_crypto_context id_cryptoctx, 5958 int catype, 5959 char *dirname) 5960 { 5961 krb5_error_code retval = EINVAL; 5962 DIR *d = NULL; 5963 struct dirent *dentry = NULL; 5964 char filename[1024]; 5965 5966 if (dirname == NULL) 5967 return EINVAL; 5968 5969 d = opendir(dirname); 5970 if (d == NULL) 5971 return ENOENT; 5972 5973 while ((dentry = readdir(d))) { 5974 if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(filename)) { 5975 pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n", 5976 __FUNCTION__, dirname, dentry->d_name); 5977 goto cleanup; 5978 } 5979 /* Ignore subdirectories and anything starting with a dot */ 5980 #ifdef DT_DIR 5981 if (dentry->d_type == DT_DIR) 5982 continue; 5983 #endif 5984 if (dentry->d_name[0] == '.') 5985 continue; 5986 (void) snprintf(filename, sizeof(filename), "%s/%s", dirname, dentry->d_name); 5987 5988 retval = load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx, 5989 id_cryptoctx, catype, filename); 5990 if (retval) 5991 goto cleanup; 5992 } 5993 5994 retval = 0; 5995 5996 cleanup: 5997 if (d != NULL) 5998 (void) closedir(d); 5999 6000 return retval; 6001 } 6002 6003 /* ARGSUSED */ 6004 krb5_error_code 6005 crypto_load_cas_and_crls(krb5_context context, 6006 pkinit_plg_crypto_context plg_cryptoctx, 6007 pkinit_req_crypto_context req_cryptoctx, 6008 pkinit_identity_opts *idopts, 6009 pkinit_identity_crypto_context id_cryptoctx, 6010 int idtype, 6011 int catype, 6012 char *id) 6013 { 6014 pkiDebug("%s: called with idtype %s and catype %s\n", 6015 __FUNCTION__, idtype2string(idtype), catype2string(catype)); 6016 /* Solaris Kerberos: Removed "break"'s as they are never reached */ 6017 switch (idtype) { 6018 case IDTYPE_FILE: 6019 return load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx, 6020 id_cryptoctx, catype, id); 6021 case IDTYPE_DIR: 6022 return load_cas_and_crls_dir(context, plg_cryptoctx, req_cryptoctx, 6023 id_cryptoctx, catype, id); 6024 default: 6025 return ENOTSUP; 6026 } 6027 } 6028 6029 static krb5_error_code 6030 create_identifiers_from_stack(STACK_OF(X509) *sk, 6031 krb5_external_principal_identifier *** ids) 6032 { 6033 krb5_error_code retval = ENOMEM; 6034 int i = 0, sk_size = sk_X509_num(sk); 6035 krb5_external_principal_identifier **krb5_cas = NULL; 6036 X509 *x = NULL; 6037 X509_NAME *xn = NULL; 6038 unsigned char *p = NULL; 6039 int len = 0; 6040 PKCS7_ISSUER_AND_SERIAL *is = NULL; 6041 char buf[DN_BUF_LEN]; 6042 6043 *ids = NULL; 6044 6045 krb5_cas = 6046 malloc((sk_size + 1) * sizeof(krb5_external_principal_identifier *)); 6047 if (krb5_cas == NULL) 6048 return ENOMEM; 6049 krb5_cas[sk_size] = NULL; 6050 6051 for (i = 0; i < sk_size; i++) { 6052 krb5_cas[i] = (krb5_external_principal_identifier *)malloc(sizeof(krb5_external_principal_identifier)); 6053 6054 x = sk_X509_value(sk, i); 6055 6056 X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf)); 6057 pkiDebug("#%d cert= %s\n", i, buf); 6058 6059 /* fill-in subjectName */ 6060 krb5_cas[i]->subjectName.magic = 0; 6061 krb5_cas[i]->subjectName.length = 0; 6062 krb5_cas[i]->subjectName.data = NULL; 6063 6064 xn = X509_get_subject_name(x); 6065 len = i2d_X509_NAME(xn, NULL); 6066 if ((p = krb5_cas[i]->subjectName.data = (unsigned char *)malloc((size_t) len)) == NULL) 6067 goto cleanup; 6068 i2d_X509_NAME(xn, &p); 6069 krb5_cas[i]->subjectName.length = len; 6070 6071 /* fill-in issuerAndSerialNumber */ 6072 krb5_cas[i]->issuerAndSerialNumber.length = 0; 6073 krb5_cas[i]->issuerAndSerialNumber.magic = 0; 6074 krb5_cas[i]->issuerAndSerialNumber.data = NULL; 6075 6076 #ifdef LONGHORN_BETA_COMPAT 6077 if (longhorn == 0) { /* XXX Longhorn doesn't like this */ 6078 #endif 6079 is = PKCS7_ISSUER_AND_SERIAL_new(); 6080 X509_NAME_set(&is->issuer, X509_get_issuer_name(x)); 6081 M_ASN1_INTEGER_free(is->serial); 6082 is->serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(x)); 6083 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL); 6084 if ((p = krb5_cas[i]->issuerAndSerialNumber.data = 6085 (unsigned char *)malloc((size_t) len)) == NULL) 6086 goto cleanup; 6087 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p); 6088 krb5_cas[i]->issuerAndSerialNumber.length = len; 6089 #ifdef LONGHORN_BETA_COMPAT 6090 } 6091 #endif 6092 6093 /* fill-in subjectKeyIdentifier */ 6094 krb5_cas[i]->subjectKeyIdentifier.length = 0; 6095 krb5_cas[i]->subjectKeyIdentifier.magic = 0; 6096 krb5_cas[i]->subjectKeyIdentifier.data = NULL; 6097 6098 6099 #ifdef LONGHORN_BETA_COMPAT 6100 if (longhorn == 0) { /* XXX Longhorn doesn't like this */ 6101 #endif 6102 if (X509_get_ext_by_NID(x, NID_subject_key_identifier, -1) >= 0) { 6103 ASN1_OCTET_STRING *ikeyid = NULL; 6104 6105 if ((ikeyid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, 6106 NULL))) { 6107 len = i2d_ASN1_OCTET_STRING(ikeyid, NULL); 6108 if ((p = krb5_cas[i]->subjectKeyIdentifier.data = 6109 (unsigned char *)malloc((size_t) len)) == NULL) 6110 goto cleanup; 6111 i2d_ASN1_OCTET_STRING(ikeyid, &p); 6112 krb5_cas[i]->subjectKeyIdentifier.length = len; 6113 } 6114 if (ikeyid != NULL) 6115 ASN1_OCTET_STRING_free(ikeyid); 6116 } 6117 #ifdef LONGHORN_BETA_COMPAT 6118 } 6119 #endif 6120 if (is != NULL) { 6121 if (is->issuer != NULL) 6122 X509_NAME_free(is->issuer); 6123 if (is->serial != NULL) 6124 ASN1_INTEGER_free(is->serial); 6125 free(is); 6126 } 6127 } 6128 6129 *ids = krb5_cas; 6130 6131 retval = 0; 6132 cleanup: 6133 if (retval) 6134 free_krb5_external_principal_identifier(&krb5_cas); 6135 6136 return retval; 6137 } 6138 6139 /* ARGSUSED */ 6140 static krb5_error_code 6141 create_krb5_invalidCertificates(krb5_context context, 6142 pkinit_plg_crypto_context plg_cryptoctx, 6143 pkinit_req_crypto_context req_cryptoctx, 6144 pkinit_identity_crypto_context id_cryptoctx, 6145 krb5_external_principal_identifier *** ids) 6146 { 6147 6148 krb5_error_code retval = ENOMEM; 6149 STACK_OF(X509) *sk = NULL; 6150 6151 *ids = NULL; 6152 if (req_cryptoctx->received_cert == NULL) 6153 return KRB5KDC_ERR_PREAUTH_FAILED; 6154 6155 sk = sk_X509_new_null(); 6156 if (sk == NULL) 6157 goto cleanup; 6158 sk_X509_push(sk, req_cryptoctx->received_cert); 6159 6160 retval = create_identifiers_from_stack(sk, ids); 6161 6162 sk_X509_free(sk); 6163 cleanup: 6164 6165 return retval; 6166 } 6167 6168 /* ARGSUSED */ 6169 krb5_error_code 6170 create_krb5_supportedCMSTypes(krb5_context context, 6171 pkinit_plg_crypto_context plg_cryptoctx, 6172 pkinit_req_crypto_context req_cryptoctx, 6173 pkinit_identity_crypto_context id_cryptoctx, 6174 krb5_algorithm_identifier ***oids) 6175 { 6176 6177 krb5_error_code retval = ENOMEM; 6178 krb5_algorithm_identifier **loids = NULL; 6179 krb5_octet_data des3oid = {0, 8, (unsigned char *)"\x2A\x86\x48\x86\xF7\x0D\x03\x07" }; 6180 6181 *oids = NULL; 6182 loids = malloc(2 * sizeof(krb5_algorithm_identifier *)); 6183 if (loids == NULL) 6184 goto cleanup; 6185 loids[1] = NULL; 6186 loids[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier)); 6187 if (loids[0] == NULL) { 6188 free(loids); 6189 goto cleanup; 6190 } 6191 retval = pkinit_copy_krb5_octet_data(&loids[0]->algorithm, &des3oid); 6192 if (retval) { 6193 free(loids[0]); 6194 free(loids); 6195 goto cleanup; 6196 } 6197 loids[0]->parameters.length = 0; 6198 loids[0]->parameters.data = NULL; 6199 6200 *oids = loids; 6201 retval = 0; 6202 cleanup: 6203 6204 return retval; 6205 } 6206 6207 /* ARGSUSED */ 6208 krb5_error_code 6209 create_krb5_trustedCertifiers(krb5_context context, 6210 pkinit_plg_crypto_context plg_cryptoctx, 6211 pkinit_req_crypto_context req_cryptoctx, 6212 pkinit_identity_crypto_context id_cryptoctx, 6213 krb5_external_principal_identifier *** ids) 6214 { 6215 6216 /* Solaris Kerberos */ 6217 STACK_OF(X509) *sk = id_cryptoctx->trustedCAs; 6218 6219 *ids = NULL; 6220 if (id_cryptoctx->trustedCAs == NULL) 6221 return KRB5KDC_ERR_PREAUTH_FAILED; 6222 6223 return create_identifiers_from_stack(sk, ids); 6224 6225 } 6226 6227 /* ARGSUSED */ 6228 krb5_error_code 6229 create_krb5_trustedCas(krb5_context context, 6230 pkinit_plg_crypto_context plg_cryptoctx, 6231 pkinit_req_crypto_context req_cryptoctx, 6232 pkinit_identity_crypto_context id_cryptoctx, 6233 int flag, 6234 krb5_trusted_ca *** ids) 6235 { 6236 krb5_error_code retval = ENOMEM; 6237 STACK_OF(X509) *sk = id_cryptoctx->trustedCAs; 6238 int i = 0, len = 0, sk_size = sk_X509_num(sk); 6239 krb5_trusted_ca **krb5_cas = NULL; 6240 X509 *x = NULL; 6241 char buf[DN_BUF_LEN]; 6242 X509_NAME *xn = NULL; 6243 unsigned char *p = NULL; 6244 PKCS7_ISSUER_AND_SERIAL *is = NULL; 6245 6246 *ids = NULL; 6247 if (id_cryptoctx->trustedCAs == NULL) 6248 return KRB5KDC_ERR_PREAUTH_FAILED; 6249 6250 krb5_cas = malloc((sk_size + 1) * sizeof(krb5_trusted_ca *)); 6251 if (krb5_cas == NULL) 6252 return ENOMEM; 6253 krb5_cas[sk_size] = NULL; 6254 6255 for (i = 0; i < sk_size; i++) { 6256 krb5_cas[i] = (krb5_trusted_ca *)malloc(sizeof(krb5_trusted_ca)); 6257 if (krb5_cas[i] == NULL) 6258 goto cleanup; 6259 x = sk_X509_value(sk, i); 6260 6261 X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf)); 6262 pkiDebug("#%d cert= %s\n", i, buf); 6263 6264 switch (flag) { 6265 case choice_trusted_cas_principalName: 6266 krb5_cas[i]->choice = choice_trusted_cas_principalName; 6267 break; 6268 case choice_trusted_cas_caName: 6269 krb5_cas[i]->choice = choice_trusted_cas_caName; 6270 krb5_cas[i]->u.caName.data = NULL; 6271 krb5_cas[i]->u.caName.length = 0; 6272 xn = X509_get_subject_name(x); 6273 len = i2d_X509_NAME(xn, NULL); 6274 if ((p = krb5_cas[i]->u.caName.data = 6275 (unsigned char *)malloc((size_t) len)) == NULL) 6276 goto cleanup; 6277 i2d_X509_NAME(xn, &p); 6278 krb5_cas[i]->u.caName.length = len; 6279 break; 6280 case choice_trusted_cas_issuerAndSerial: 6281 krb5_cas[i]->choice = choice_trusted_cas_issuerAndSerial; 6282 krb5_cas[i]->u.issuerAndSerial.data = NULL; 6283 krb5_cas[i]->u.issuerAndSerial.length = 0; 6284 is = PKCS7_ISSUER_AND_SERIAL_new(); 6285 X509_NAME_set(&is->issuer, X509_get_issuer_name(x)); 6286 M_ASN1_INTEGER_free(is->serial); 6287 is->serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(x)); 6288 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL); 6289 if ((p = krb5_cas[i]->u.issuerAndSerial.data = 6290 (unsigned char *)malloc((size_t) len)) == NULL) 6291 goto cleanup; 6292 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p); 6293 krb5_cas[i]->u.issuerAndSerial.length = len; 6294 if (is != NULL) { 6295 if (is->issuer != NULL) 6296 X509_NAME_free(is->issuer); 6297 if (is->serial != NULL) 6298 ASN1_INTEGER_free(is->serial); 6299 free(is); 6300 } 6301 break; 6302 default: break; 6303 } 6304 } 6305 retval = 0; 6306 *ids = krb5_cas; 6307 cleanup: 6308 if (retval) 6309 free_krb5_trusted_ca(&krb5_cas); 6310 6311 return retval; 6312 } 6313 6314 /* ARGSUSED */ 6315 krb5_error_code 6316 create_issuerAndSerial(krb5_context context, 6317 pkinit_plg_crypto_context plg_cryptoctx, 6318 pkinit_req_crypto_context req_cryptoctx, 6319 pkinit_identity_crypto_context id_cryptoctx, 6320 unsigned char **out, 6321 unsigned int *out_len) 6322 { 6323 unsigned char *p = NULL; 6324 PKCS7_ISSUER_AND_SERIAL *is = NULL; 6325 int len = 0; 6326 krb5_error_code retval = ENOMEM; 6327 X509 *cert = req_cryptoctx->received_cert; 6328 6329 *out = NULL; 6330 *out_len = 0; 6331 if (req_cryptoctx->received_cert == NULL) 6332 return 0; 6333 6334 is = PKCS7_ISSUER_AND_SERIAL_new(); 6335 X509_NAME_set(&is->issuer, X509_get_issuer_name(cert)); 6336 M_ASN1_INTEGER_free(is->serial); 6337 is->serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(cert)); 6338 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL); 6339 if ((p = *out = (unsigned char *)malloc((size_t) len)) == NULL) 6340 goto cleanup; 6341 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p); 6342 *out_len = len; 6343 retval = 0; 6344 6345 cleanup: 6346 X509_NAME_free(is->issuer); 6347 ASN1_INTEGER_free(is->serial); 6348 free(is); 6349 6350 return retval; 6351 } 6352 6353 static int 6354 pkcs7_decrypt(krb5_context context, 6355 pkinit_identity_crypto_context id_cryptoctx, 6356 PKCS7 *p7, 6357 BIO *data) 6358 { 6359 BIO *tmpmem = NULL; 6360 /* Solaris Kerberos */ 6361 int i = 0; 6362 char buf[4096]; 6363 6364 if(p7 == NULL) 6365 return 0; 6366 6367 if(!PKCS7_type_is_enveloped(p7)) { 6368 pkiDebug("wrong pkcs7 content type\n"); 6369 return 0; 6370 } 6371 6372 if(!(tmpmem = pkcs7_dataDecode(context, id_cryptoctx, p7))) { 6373 pkiDebug("unable to decrypt pkcs7 object\n"); 6374 return 0; 6375 } 6376 /* Solaris Kerberos: Suppress sun studio compiler warning */ 6377 #pragma error_messages (off, E_END_OF_LOOP_CODE_NOT_REACHED) 6378 for(;;) { 6379 i = BIO_read(tmpmem, buf, sizeof(buf)); 6380 if (i <= 0) break; 6381 BIO_write(data, buf, i); 6382 BIO_free_all(tmpmem); 6383 return 1; 6384 } 6385 #pragma error_messages (default, E_END_OF_LOOP_CODE_NOT_REACHED) 6386 6387 return 0; 6388 } 6389 6390 krb5_error_code 6391 pkinit_process_td_trusted_certifiers( 6392 krb5_context context, 6393 pkinit_plg_crypto_context plg_cryptoctx, 6394 pkinit_req_crypto_context req_cryptoctx, 6395 pkinit_identity_crypto_context id_cryptoctx, 6396 krb5_external_principal_identifier **krb5_trusted_certifiers, 6397 int td_type) 6398 { 6399 krb5_error_code retval = ENOMEM; 6400 STACK_OF(X509_NAME) *sk_xn = NULL; 6401 X509_NAME *xn = NULL; 6402 PKCS7_ISSUER_AND_SERIAL *is = NULL; 6403 ASN1_OCTET_STRING *id = NULL; 6404 const unsigned char *p = NULL; 6405 char buf[DN_BUF_LEN]; 6406 int i = 0; 6407 6408 if (td_type == TD_TRUSTED_CERTIFIERS) 6409 pkiDebug("received trusted certifiers\n"); 6410 else 6411 pkiDebug("received invalid certificate\n"); 6412 6413 sk_xn = sk_X509_NAME_new_null(); 6414 while(krb5_trusted_certifiers[i] != NULL) { 6415 if (krb5_trusted_certifiers[i]->subjectName.data != NULL) { 6416 p = krb5_trusted_certifiers[i]->subjectName.data; 6417 xn = d2i_X509_NAME(NULL, &p, 6418 (int)krb5_trusted_certifiers[i]->subjectName.length); 6419 if (xn == NULL) 6420 goto cleanup; 6421 X509_NAME_oneline(xn, buf, sizeof(buf)); 6422 if (td_type == TD_TRUSTED_CERTIFIERS) 6423 pkiDebug("#%d cert = %s is trusted by kdc\n", i, buf); 6424 else 6425 pkiDebug("#%d cert = %s is invalid\n", i, buf); 6426 sk_X509_NAME_push(sk_xn, xn); 6427 } 6428 6429 if (krb5_trusted_certifiers[i]->issuerAndSerialNumber.data != NULL) { 6430 p = krb5_trusted_certifiers[i]->issuerAndSerialNumber.data; 6431 is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p, 6432 (int)krb5_trusted_certifiers[i]->issuerAndSerialNumber.length); 6433 if (is == NULL) 6434 goto cleanup; 6435 X509_NAME_oneline(is->issuer, buf, sizeof(buf)); 6436 if (td_type == TD_TRUSTED_CERTIFIERS) 6437 pkiDebug("#%d issuer = %s serial = %ld is trusted bu kdc\n", i, 6438 buf, ASN1_INTEGER_get(is->serial)); 6439 else 6440 pkiDebug("#%d issuer = %s serial = %ld is invalid\n", i, buf, 6441 ASN1_INTEGER_get(is->serial)); 6442 PKCS7_ISSUER_AND_SERIAL_free(is); 6443 } 6444 6445 if (krb5_trusted_certifiers[i]->subjectKeyIdentifier.data != NULL) { 6446 p = krb5_trusted_certifiers[i]->subjectKeyIdentifier.data; 6447 id = d2i_ASN1_OCTET_STRING(NULL, &p, 6448 (int)krb5_trusted_certifiers[i]->subjectKeyIdentifier.length); 6449 if (id == NULL) 6450 goto cleanup; 6451 /* XXX */ 6452 ASN1_OCTET_STRING_free(id); 6453 } 6454 i++; 6455 } 6456 /* XXX Since we not doing anything with received trusted certifiers 6457 * return an error. this is the place where we can pick a different 6458 * client certificate based on the information in td_trusted_certifiers 6459 */ 6460 retval = KRB5KDC_ERR_PREAUTH_FAILED; 6461 cleanup: 6462 if (sk_xn != NULL) 6463 sk_X509_NAME_pop_free(sk_xn, X509_NAME_free); 6464 6465 return retval; 6466 } 6467 6468 static BIO * 6469 pkcs7_dataDecode(krb5_context context, 6470 pkinit_identity_crypto_context id_cryptoctx, 6471 PKCS7 *p7) 6472 { 6473 int i = 0; 6474 unsigned int jj = 0, tmp_len = 0; 6475 BIO *out=NULL,*etmp=NULL,*bio=NULL; 6476 unsigned char *tmp=NULL; 6477 ASN1_OCTET_STRING *data_body=NULL; 6478 const EVP_CIPHER *evp_cipher=NULL; 6479 EVP_CIPHER_CTX *evp_ctx=NULL; 6480 X509_ALGOR *enc_alg=NULL; 6481 STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; 6482 /* Solaris Kerberos: Not used */ 6483 #if 0 6484 X509_ALGOR *xalg=NULL; 6485 #endif 6486 PKCS7_RECIP_INFO *ri=NULL; 6487 X509 *cert = sk_X509_value(id_cryptoctx->my_certs, 6488 id_cryptoctx->cert_index); 6489 6490 p7->state=PKCS7_S_HEADER; 6491 6492 rsk=p7->d.enveloped->recipientinfo; 6493 enc_alg=p7->d.enveloped->enc_data->algorithm; 6494 data_body=p7->d.enveloped->enc_data->enc_data; 6495 evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm); 6496 if (evp_cipher == NULL) { 6497 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); 6498 goto cleanup; 6499 } 6500 /* Solaris Kerberos: Not used */ 6501 #if 0 6502 xalg=p7->d.enveloped->enc_data->algorithm; 6503 #endif 6504 6505 if ((etmp=BIO_new(BIO_f_cipher())) == NULL) { 6506 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); 6507 goto cleanup; 6508 } 6509 6510 /* It was encrypted, we need to decrypt the secret key 6511 * with the private key */ 6512 6513 /* Find the recipientInfo which matches the passed certificate 6514 * (if any) 6515 */ 6516 6517 if (cert) { 6518 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { 6519 int tmp_ret = 0; 6520 ri=sk_PKCS7_RECIP_INFO_value(rsk,i); 6521 tmp_ret = X509_NAME_cmp(ri->issuer_and_serial->issuer, 6522 cert->cert_info->issuer); 6523 if (!tmp_ret) { 6524 tmp_ret = M_ASN1_INTEGER_cmp(cert->cert_info->serialNumber, 6525 ri->issuer_and_serial->serial); 6526 if (!tmp_ret) 6527 break; 6528 } 6529 ri=NULL; 6530 } 6531 if (ri == NULL) { 6532 PKCS7err(PKCS7_F_PKCS7_DATADECODE, 6533 PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); 6534 goto cleanup; 6535 } 6536 6537 } 6538 6539 /* If we haven't got a certificate try each ri in turn */ 6540 6541 if (cert == NULL) { 6542 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { 6543 ri=sk_PKCS7_RECIP_INFO_value(rsk,i); 6544 jj = pkinit_decode_data(context, id_cryptoctx, 6545 M_ASN1_STRING_data(ri->enc_key), 6546 (unsigned int) M_ASN1_STRING_length(ri->enc_key), 6547 &tmp, &tmp_len); 6548 if (jj) { 6549 PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB); 6550 goto cleanup; 6551 } 6552 6553 if (!jj && tmp_len > 0) { 6554 jj = tmp_len; 6555 break; 6556 } 6557 6558 ERR_clear_error(); 6559 ri = NULL; 6560 } 6561 6562 if (ri == NULL) { 6563 PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_RECIPIENT_MATCHES_KEY); 6564 goto cleanup; 6565 } 6566 } 6567 else { 6568 jj = pkinit_decode_data(context, id_cryptoctx, 6569 M_ASN1_STRING_data(ri->enc_key), 6570 (unsigned int) M_ASN1_STRING_length(ri->enc_key), 6571 &tmp, &tmp_len); 6572 /* Solaris Kerberos: tmp_len is unsigned. Cannot be < 0 */ 6573 if (jj || tmp_len == 0) { 6574 PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB); 6575 goto cleanup; 6576 } 6577 jj = tmp_len; 6578 } 6579 6580 evp_ctx=NULL; 6581 BIO_get_cipher_ctx(etmp,&evp_ctx); 6582 if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0) 6583 goto cleanup; 6584 if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0) 6585 goto cleanup; 6586 6587 if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) { 6588 /* Some S/MIME clients don't use the same key 6589 * and effective key length. The key length is 6590 * determined by the size of the decrypted RSA key. 6591 */ 6592 if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, (int)jj)) { 6593 PKCS7err(PKCS7_F_PKCS7_DATADECODE, 6594 PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH); 6595 goto cleanup; 6596 } 6597 } 6598 if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0) 6599 goto cleanup; 6600 6601 OPENSSL_cleanse(tmp,jj); 6602 6603 if (out == NULL) 6604 out=etmp; 6605 else 6606 BIO_push(out,etmp); 6607 etmp=NULL; 6608 6609 if (data_body->length > 0) 6610 bio = BIO_new_mem_buf(data_body->data, data_body->length); 6611 else { 6612 bio=BIO_new(BIO_s_mem()); 6613 BIO_set_mem_eof_return(bio,0); 6614 } 6615 BIO_push(out,bio); 6616 bio=NULL; 6617 6618 /* Solaris Kerberos */ 6619 goto out; 6620 6621 cleanup: 6622 if (out != NULL) BIO_free_all(out); 6623 if (etmp != NULL) BIO_free_all(etmp); 6624 if (bio != NULL) BIO_free_all(bio); 6625 out=NULL; 6626 6627 out: 6628 if (tmp != NULL) 6629 free(tmp); 6630 6631 return(out); 6632 } 6633 6634 static krb5_error_code 6635 der_decode_data(unsigned char *data, long data_len, 6636 unsigned char **out, long *out_len) 6637 { 6638 /* Solaris Kerberos */ 6639 krb5_error_code retval = KRB5KRB_ERR_GENERIC; 6640 ASN1_OCTET_STRING *s = NULL; 6641 const unsigned char *p = data; 6642 6643 if ((s = d2i_ASN1_BIT_STRING(NULL, &p, data_len)) == NULL) 6644 goto cleanup; 6645 *out_len = s->length; 6646 if ((*out = (unsigned char *) malloc((size_t) *out_len + 1)) == NULL) { 6647 retval = ENOMEM; 6648 goto cleanup; 6649 } 6650 (void) memcpy(*out, s->data, (size_t) s->length); 6651 (*out)[s->length] = '\0'; 6652 6653 retval = 0; 6654 cleanup: 6655 if (s != NULL) 6656 ASN1_OCTET_STRING_free(s); 6657 6658 return retval; 6659 } 6660 6661 6662 #ifdef DEBUG_DH 6663 static void 6664 print_dh(DH * dh, char *msg) 6665 { 6666 BIO *bio_err = NULL; 6667 6668 bio_err = BIO_new(BIO_s_file()); 6669 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); 6670 6671 if (msg) 6672 BIO_puts(bio_err, (const char *)msg); 6673 if (dh) 6674 DHparams_print(bio_err, dh); 6675 6676 BN_print(bio_err, dh->q); 6677 BIO_puts(bio_err, (const char *)"\n"); 6678 BIO_free(bio_err); 6679 6680 } 6681 6682 static void 6683 print_pubkey(BIGNUM * key, char *msg) 6684 { 6685 BIO *bio_err = NULL; 6686 6687 bio_err = BIO_new(BIO_s_file()); 6688 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); 6689 6690 if (msg) 6691 BIO_puts(bio_err, (const char *)msg); 6692 if (key) 6693 BN_print(bio_err, key); 6694 BIO_puts(bio_err, "\n"); 6695 6696 BIO_free(bio_err); 6697 6698 } 6699 #endif 6700 6701 /* 6702 * Solaris Kerberos: 6703 * Error message generation has changed so gettext() can be used 6704 */ 6705 #if 0 6706 static char * 6707 pkinit_pkcs11_code_to_text(int err) 6708 { 6709 int i; 6710 static char uc[64]; 6711 6712 for (i = 0; pkcs11_errstrings[i].text != NULL; i++) 6713 if (pkcs11_errstrings[i].code == err) 6714 break; 6715 if (pkcs11_errstrings[i].text != NULL) 6716 return (pkcs11_errstrings[i].text); 6717 snprintf(uc, 64, gettext("unknown code 0x%x"), err); 6718 return (uc); 6719 } 6720 #endif 6721 6722 static char * 6723 pkinit_pkcs11_code_to_text(int err) { 6724 return pkcs11_error_table(err); 6725 }