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