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