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