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