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