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