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