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