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 /* Solaris Kerberos - Changes for gettext() */ 3358 prompt_len = sizeof (tip->label) + 256; 3359 if ((prompt = (char *) malloc(prompt_len)) == NULL) 3360 return ENOMEM; 3361 (void) snprintf(prompt, prompt_len, gettext("%.*s PIN"), sizeof (tip->label), tip->label); 3362 /* Solaris Kerberos */ 3363 if (tip->flags & CKF_USER_PIN_LOCKED) 3364 (void) strlcat(prompt, gettext(" (Warning: PIN locked)"), prompt_len); 3365 else if (tip->flags & CKF_USER_PIN_FINAL_TRY) 3366 (void) strlcat(prompt, gettext(" (Warning: PIN final try)"), prompt_len); 3367 else if (tip->flags & CKF_USER_PIN_COUNT_LOW) 3368 (void) strlcat(prompt, gettext(" (Warning: PIN count low)"), prompt_len); 3369 rdat.data = (char *)malloc(tip->ulMaxPinLen + 2); 3370 rdat.length = tip->ulMaxPinLen + 1; 3371 3372 kprompt.prompt = prompt; 3373 kprompt.hidden = 1; 3374 kprompt.reply = &rdat; 3375 prompt_type = KRB5_PROMPT_TYPE_PREAUTH; 3376 3377 /* PROMPTER_INVOCATION */ 3378 k5int_set_prompt_types(context, &prompt_type); 3379 r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data, 3380 NULL, NULL, 1, &kprompt); 3381 k5int_set_prompt_types(context, 0); 3382 free(prompt); 3383 } 3384 3385 if (r == 0) { 3386 r = id_cryptoctx->p11->C_Login(id_cryptoctx->session, CKU_USER, 3387 (u_char *) rdat.data, rdat.length); 3388 3389 if (r != CKR_OK) { 3390 pkiDebug("C_Login: %s\n", pkinit_pkcs11_code_to_text(r)); 3391 /* Solaris Kerberos: Improved error messages */ 3392 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, 3393 gettext("failed to log into token: %s"), 3394 pkinit_pkcs11_code_to_text(r)); 3395 r = KRB5KDC_ERR_PREAUTH_FAILED; 3396 } else { 3397 /* Solaris Kerberos: only need to login once */ 3398 id_cryptoctx->p11flags |= C_LOGIN_DONE; 3399 } 3400 } 3401 if (rdat.data) 3402 free(rdat.data); 3403 3404 return r; 3405 } 3406 3407 static krb5_error_code 3408 pkinit_open_session(krb5_context context, 3409 pkinit_identity_crypto_context cctx) 3410 { 3411 int i, r; 3412 unsigned char *cp; 3413 CK_ULONG count = 0; 3414 CK_SLOT_ID_PTR slotlist; 3415 CK_TOKEN_INFO tinfo; 3416 3417 if (cctx->p11_module != NULL) 3418 return 0; /* session already open */ 3419 3420 /* Load module */ 3421 cctx->p11_module = 3422 pkinit_C_LoadModule(cctx->p11_module_name, &cctx->p11); 3423 if (cctx->p11_module == NULL) 3424 return KRB5KDC_ERR_PREAUTH_FAILED; 3425 3426 /* Init */ 3427 /* Solaris Kerberos: Don't fail if cryptoki is already initialized */ 3428 r = cctx->p11->C_Initialize(NULL); 3429 if (r != CKR_OK && r != CKR_CRYPTOKI_ALREADY_INITIALIZED) { 3430 pkiDebug("C_Initialize: %s\n", pkinit_pkcs11_code_to_text(r)); 3431 return KRB5KDC_ERR_PREAUTH_FAILED; 3432 } 3433 3434 /* 3435 * Solaris Kerberos: 3436 * If C_Initialize was already called by the process before the pkinit 3437 * module was loaded then record that fact. 3438 * "finalize_pkcs11" is used by pkinit_fini_pkcs11 to determine whether 3439 * or not C_Finalize() should be called. 3440 */ 3441 cctx->finalize_pkcs11 = 3442 (r == CKR_CRYPTOKI_ALREADY_INITIALIZED ? FALSE : TRUE); 3443 3444 /* Get the list of available slots */ 3445 if (cctx->slotid != PK_NOSLOT) { 3446 /* A slot was specified, so that's the only one in the list */ 3447 count = 1; 3448 slotlist = (CK_SLOT_ID_PTR) malloc(sizeof (CK_SLOT_ID)); 3449 slotlist[0] = cctx->slotid; 3450 } else { 3451 if (cctx->p11->C_GetSlotList(TRUE, NULL, &count) != CKR_OK) 3452 return KRB5KDC_ERR_PREAUTH_FAILED; 3453 if (count == 0) 3454 return KRB5KDC_ERR_PREAUTH_FAILED; 3455 slotlist = (CK_SLOT_ID_PTR) malloc(count * sizeof (CK_SLOT_ID)); 3456 if (cctx->p11->C_GetSlotList(TRUE, slotlist, &count) != CKR_OK) 3457 return KRB5KDC_ERR_PREAUTH_FAILED; 3458 } 3459 3460 /* Look for the given token label, or if none given take the first one */ 3461 for (i = 0; i < count; i++) { 3462 /* Open session */ 3463 if ((r = cctx->p11->C_OpenSession(slotlist[i], CKF_SERIAL_SESSION, 3464 NULL, NULL, &cctx->session)) != CKR_OK) { 3465 pkiDebug("C_OpenSession: %s\n", pkinit_pkcs11_code_to_text(r)); 3466 return KRB5KDC_ERR_PREAUTH_FAILED; 3467 } 3468 3469 /* Get token info */ 3470 if ((r = cctx->p11->C_GetTokenInfo(slotlist[i], &tinfo)) != CKR_OK) { 3471 pkiDebug("C_GetTokenInfo: %s\n", pkinit_pkcs11_code_to_text(r)); 3472 return KRB5KDC_ERR_PREAUTH_FAILED; 3473 } 3474 for (cp = tinfo.label + sizeof (tinfo.label) - 1; 3475 *cp == '\0' || *cp == ' '; cp--) 3476 *cp = '\0'; 3477 pkiDebug("open_session: slotid %d token \"%s\"\n", 3478 (int) slotlist[i], tinfo.label); 3479 if (cctx->token_label == NULL || 3480 !strcmp((char *) cctx->token_label, (char *) tinfo.label)) 3481 break; 3482 cctx->p11->C_CloseSession(cctx->session); 3483 } 3484 if (i >= count) { 3485 free(slotlist); 3486 pkiDebug("open_session: no matching token found\n"); 3487 return KRB5KDC_ERR_PREAUTH_FAILED; 3488 } 3489 cctx->slotid = slotlist[i]; 3490 free(slotlist); 3491 pkiDebug("open_session: slotid %d (%d of %d)\n", (int) cctx->slotid, 3492 i + 1, (int) count); 3493 3494 /* Login if needed */ 3495 /* Solaris Kerberos: added cctx->p11flags check */ 3496 if (tinfo.flags & CKF_LOGIN_REQUIRED && ! (cctx->p11flags & C_LOGIN_DONE)) 3497 r = pkinit_login(context, cctx, &tinfo); 3498 3499 return r; 3500 } 3501 3502 /* 3503 * Look for a key that's: 3504 * 1. private 3505 * 2. capable of the specified operation (usually signing or decrypting) 3506 * 3. RSA (this may be wrong but it's all we can do for now) 3507 * 4. matches the id of the cert we chose 3508 * 3509 * You must call pkinit_get_certs before calling pkinit_find_private_key 3510 * (that's because we need the ID of the private key) 3511 * 3512 * pkcs11 says the id of the key doesn't have to match that of the cert, but 3513 * I can't figure out any other way to decide which key to use. 3514 * 3515 * We should only find one key that fits all the requirements. 3516 * If there are more than one, we just take the first one. 3517 */ 3518 3519 /* ARGSUSED */ 3520 krb5_error_code 3521 pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx, 3522 CK_ATTRIBUTE_TYPE usage, 3523 CK_OBJECT_HANDLE *objp) 3524 { 3525 CK_OBJECT_CLASS cls; 3526 CK_ATTRIBUTE attrs[4]; 3527 CK_ULONG count; 3528 CK_KEY_TYPE keytype; 3529 unsigned int nattrs = 0; 3530 int r; 3531 #ifdef PKINIT_USE_KEY_USAGE 3532 CK_BBOOL true_false; 3533 #endif 3534 3535 cls = CKO_PRIVATE_KEY; 3536 attrs[nattrs].type = CKA_CLASS; 3537 attrs[nattrs].pValue = &cls; 3538 attrs[nattrs].ulValueLen = sizeof cls; 3539 nattrs++; 3540 3541 #ifdef PKINIT_USE_KEY_USAGE 3542 /* 3543 * Some cards get confused if you try to specify a key usage, 3544 * so don't, and hope for the best. This will fail if you have 3545 * several keys with the same id and different usages but I have 3546 * not seen this on real cards. 3547 */ 3548 true_false = TRUE; 3549 attrs[nattrs].type = usage; 3550 attrs[nattrs].pValue = &true_false; 3551 attrs[nattrs].ulValueLen = sizeof true_false; 3552 nattrs++; 3553 #endif 3554 3555 keytype = CKK_RSA; 3556 attrs[nattrs].type = CKA_KEY_TYPE; 3557 attrs[nattrs].pValue = &keytype; 3558 attrs[nattrs].ulValueLen = sizeof keytype; 3559 nattrs++; 3560 3561 attrs[nattrs].type = CKA_ID; 3562 attrs[nattrs].pValue = id_cryptoctx->cert_id; 3563 attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len; 3564 nattrs++; 3565 3566 r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs); 3567 if (r != CKR_OK) { 3568 pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n", 3569 pkinit_pkcs11_code_to_text(r)); 3570 return KRB5KDC_ERR_PREAUTH_FAILED; 3571 } 3572 3573 r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, objp, 1, &count); 3574 id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session); 3575 pkiDebug("found %d private keys (%s)\n", (int) count, pkinit_pkcs11_code_to_text(r)); 3576 3577 /* 3578 * Solaris Kerberos: 3579 * The CKA_ID may not be correctly set for the private key. For e.g. when 3580 * storing a private key in softtoken pktool(1) doesn't generate or store 3581 * a CKA_ID for the private key. Another way to identify the private key is 3582 * to look for a private key with the same RSA modulus as the public key 3583 * in the certificate. 3584 */ 3585 if (r == CKR_OK && count != 1) { 3586 3587 EVP_PKEY *priv; 3588 X509 *cert; 3589 unsigned int n_len; 3590 unsigned char *n_bytes; 3591 3592 cert = sk_X509_value(id_cryptoctx->my_certs, 0); 3593 priv = X509_get_pubkey(cert); 3594 if (priv == NULL) { 3595 pkiDebug("Failed to extract pub key from cert\n"); 3596 return KRB5KDC_ERR_PREAUTH_FAILED; 3597 } 3598 3599 nattrs = 0; 3600 cls = CKO_PRIVATE_KEY; 3601 attrs[nattrs].type = CKA_CLASS; 3602 attrs[nattrs].pValue = &cls; 3603 attrs[nattrs].ulValueLen = sizeof cls; 3604 nattrs++; 3605 3606 #ifdef PKINIT_USE_KEY_USAGE 3607 true_false = TRUE; 3608 attrs[nattrs].type = usage; 3609 attrs[nattrs].pValue = &true_false; 3610 attrs[nattrs].ulValueLen = sizeof true_false; 3611 nattrs++; 3612 #endif 3613 3614 keytype = CKK_RSA; 3615 attrs[nattrs].type = CKA_KEY_TYPE; 3616 attrs[nattrs].pValue = &keytype; 3617 attrs[nattrs].ulValueLen = sizeof keytype; 3618 nattrs++; 3619 3620 n_len = BN_num_bytes(priv->pkey.rsa->n); 3621 n_bytes = (unsigned char *) malloc((size_t) n_len); 3622 if (n_bytes == NULL) { 3623 return (ENOMEM); 3624 } 3625 3626 if (BN_bn2bin(priv->pkey.rsa->n, n_bytes) == 0) { 3627 free (n_bytes); 3628 pkiDebug("zero-byte key modulus\n"); 3629 return KRB5KDC_ERR_PREAUTH_FAILED; 3630 } 3631 3632 attrs[nattrs].type = CKA_MODULUS; 3633 attrs[nattrs].ulValueLen = n_len; 3634 attrs[nattrs].pValue = n_bytes; 3635 3636 nattrs++; 3637 3638 r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs); 3639 free (n_bytes); 3640 if (r != CKR_OK) { 3641 pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n", 3642 pkinit_pkcs11_code_to_text(r)); 3643 return KRB5KDC_ERR_PREAUTH_FAILED; 3644 } 3645 3646 r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, objp, 1, &count); 3647 id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session); 3648 pkiDebug("found %d private keys (%s)\n", (int) count, pkinit_pkcs11_code_to_text(r)); 3649 3650 } 3651 3652 if (r != CKR_OK || count < 1) 3653 return KRB5KDC_ERR_PREAUTH_FAILED; 3654 return 0; 3655 } 3656 #endif 3657 3658 /* ARGSUSED */ 3659 static krb5_error_code 3660 pkinit_decode_data_fs(krb5_context context, 3661 pkinit_identity_crypto_context id_cryptoctx, 3662 unsigned char *data, 3663 unsigned int data_len, 3664 unsigned char **decoded_data, 3665 unsigned int *decoded_data_len) 3666 { 3667 if (decode_data(decoded_data, decoded_data_len, data, data_len, 3668 id_cryptoctx->my_key, sk_X509_value(id_cryptoctx->my_certs, 3669 id_cryptoctx->cert_index)) <= 0) { 3670 pkiDebug("failed to decode data\n"); 3671 return KRB5KDC_ERR_PREAUTH_FAILED; 3672 } 3673 return 0; 3674 } 3675 3676 #ifndef WITHOUT_PKCS11 3677 #ifdef SILLYDECRYPT 3678 CK_RV 3679 pkinit_C_Decrypt(pkinit_identity_crypto_context id_cryptoctx, 3680 CK_BYTE_PTR pEncryptedData, 3681 CK_ULONG ulEncryptedDataLen, 3682 CK_BYTE_PTR pData, 3683 CK_ULONG_PTR pulDataLen) 3684 { 3685 CK_RV rv = CKR_OK; 3686 3687 rv = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, pEncryptedData, 3688 ulEncryptedDataLen, pData, pulDataLen); 3689 if (rv == CKR_OK) { 3690 pkiDebug("pData %x *pulDataLen %d\n", (int) pData, (int) *pulDataLen); 3691 } 3692 return rv; 3693 } 3694 #endif 3695 3696 static krb5_error_code 3697 pkinit_decode_data_pkcs11(krb5_context context, 3698 pkinit_identity_crypto_context id_cryptoctx, 3699 unsigned char *data, 3700 unsigned int data_len, 3701 unsigned char **decoded_data, 3702 unsigned int *decoded_data_len) 3703 { 3704 CK_OBJECT_HANDLE obj; 3705 CK_ULONG len; 3706 CK_MECHANISM mech; 3707 unsigned char *cp; 3708 int r; 3709 3710 if (pkinit_open_session(context, id_cryptoctx)) { 3711 pkiDebug("can't open pkcs11 session\n"); 3712 return KRB5KDC_ERR_PREAUTH_FAILED; 3713 } 3714 3715 /* Solaris Kerberos: Login, if needed, to access private object */ 3716 if (!(id_cryptoctx->p11flags & C_LOGIN_DONE)) { 3717 CK_TOKEN_INFO tinfo; 3718 3719 r = id_cryptoctx->p11->C_GetTokenInfo(id_cryptoctx->slotid, &tinfo); 3720 if (r != 0) 3721 return r; 3722 3723 r = pkinit_login(context, id_cryptoctx, &tinfo); 3724 if (r != 0) 3725 return r; 3726 } 3727 3728 r = pkinit_find_private_key(id_cryptoctx, CKA_DECRYPT, &obj); 3729 if (r != 0) 3730 return r; 3731 3732 mech.mechanism = CKM_RSA_PKCS; 3733 mech.pParameter = NULL; 3734 mech.ulParameterLen = 0; 3735 3736 if ((r = id_cryptoctx->p11->C_DecryptInit(id_cryptoctx->session, &mech, 3737 obj)) != CKR_OK) { 3738 pkiDebug("C_DecryptInit: 0x%x\n", (int) r); 3739 return KRB5KDC_ERR_PREAUTH_FAILED; 3740 } 3741 pkiDebug("data_len = %d\n", data_len); 3742 cp = (unsigned char *)malloc((size_t) data_len); 3743 if (cp == NULL) 3744 return ENOMEM; 3745 len = data_len; 3746 #ifdef SILLYDECRYPT 3747 pkiDebug("session %x edata %x edata_len %d data %x datalen @%x %d\n", 3748 (int) id_cryptoctx->session, (int) data, (int) data_len, (int) cp, 3749 (int) &len, (int) len); 3750 if ((r = pkinit_C_Decrypt(id_cryptoctx, data, (CK_ULONG) data_len, 3751 cp, &len)) != CKR_OK) { 3752 #else 3753 if ((r = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, data, 3754 (CK_ULONG) data_len, cp, &len)) != CKR_OK) { 3755 #endif 3756 pkiDebug("C_Decrypt: %s\n", pkinit_pkcs11_code_to_text(r)); 3757 if (r == CKR_BUFFER_TOO_SMALL) 3758 pkiDebug("decrypt %d needs %d\n", (int) data_len, (int) len); 3759 return KRB5KDC_ERR_PREAUTH_FAILED; 3760 } 3761 pkiDebug("decrypt %d -> %d\n", (int) data_len, (int) len); 3762 *decoded_data_len = len; 3763 *decoded_data = cp; 3764 3765 return 0; 3766 } 3767 #endif 3768 3769 krb5_error_code 3770 pkinit_decode_data(krb5_context context, 3771 pkinit_identity_crypto_context id_cryptoctx, 3772 unsigned char *data, 3773 unsigned int data_len, 3774 unsigned char **decoded_data, 3775 unsigned int *decoded_data_len) 3776 { 3777 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; 3778 3779 if (id_cryptoctx->pkcs11_method != 1) 3780 retval = pkinit_decode_data_fs(context, id_cryptoctx, data, data_len, 3781 decoded_data, decoded_data_len); 3782 #ifndef WITHOUT_PKCS11 3783 else 3784 retval = pkinit_decode_data_pkcs11(context, id_cryptoctx, data, 3785 data_len, decoded_data, decoded_data_len); 3786 #endif 3787 3788 return retval; 3789 } 3790 3791 /* ARGSUSED */ 3792 static krb5_error_code 3793 pkinit_sign_data_fs(krb5_context context, 3794 pkinit_identity_crypto_context id_cryptoctx, 3795 unsigned char *data, 3796 unsigned int data_len, 3797 unsigned char **sig, 3798 unsigned int *sig_len) 3799 { 3800 if (create_signature(sig, sig_len, data, data_len, 3801 id_cryptoctx->my_key) != 0) { 3802 pkiDebug("failed to create the signature\n"); 3803 return KRB5KDC_ERR_PREAUTH_FAILED; 3804 } 3805 return 0; 3806 } 3807 3808 #ifndef WITHOUT_PKCS11 3809 static krb5_error_code 3810 pkinit_sign_data_pkcs11(krb5_context context, 3811 pkinit_identity_crypto_context id_cryptoctx, 3812 unsigned char *data, 3813 unsigned int data_len, 3814 unsigned char **sig, 3815 unsigned int *sig_len) 3816 { 3817 CK_OBJECT_HANDLE obj; 3818 CK_ULONG len; 3819 CK_MECHANISM mech; 3820 unsigned char *cp; 3821 int r; 3822 3823 if (pkinit_open_session(context, id_cryptoctx)) { 3824 pkiDebug("can't open pkcs11 session\n"); 3825 return KRB5KDC_ERR_PREAUTH_FAILED; 3826 } 3827 3828 /* Solaris Kerberos: Login, if needed, to access private object */ 3829 if (!(id_cryptoctx->p11flags & C_LOGIN_DONE)) { 3830 CK_TOKEN_INFO tinfo; 3831 3832 r = id_cryptoctx->p11->C_GetTokenInfo(id_cryptoctx->slotid, &tinfo); 3833 if (r != 0) 3834 return r; 3835 3836 r = pkinit_login(context, id_cryptoctx, &tinfo); 3837 if (r != 0) 3838 return r; 3839 } 3840 3841 r = pkinit_find_private_key(id_cryptoctx, CKA_SIGN, &obj); 3842 if (r != 0 ) 3843 return r; 3844 3845 mech.mechanism = id_cryptoctx->mech; 3846 mech.pParameter = NULL; 3847 mech.ulParameterLen = 0; 3848 3849 if ((r = id_cryptoctx->p11->C_SignInit(id_cryptoctx->session, &mech, 3850 obj)) != CKR_OK) { 3851 pkiDebug("C_SignInit: %s\n", pkinit_pkcs11_code_to_text(r)); 3852 return KRB5KDC_ERR_PREAUTH_FAILED; 3853 } 3854 3855 /* 3856 * Key len would give an upper bound on sig size, but there's no way to 3857 * get that. So guess, and if it's too small, re-malloc. 3858 */ 3859 len = PK_SIGLEN_GUESS; 3860 cp = (unsigned char *)malloc((size_t) len); 3861 if (cp == NULL) 3862 return ENOMEM; 3863 3864 r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data, 3865 (CK_ULONG) data_len, cp, &len); 3866 if (r == CKR_BUFFER_TOO_SMALL || (r == CKR_OK && len >= PK_SIGLEN_GUESS)) { 3867 free(cp); 3868 pkiDebug("C_Sign realloc %d\n", (int) len); 3869 cp = (unsigned char *)malloc((size_t) len); 3870 r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data, 3871 (CK_ULONG) data_len, cp, &len); 3872 } 3873 if (r != CKR_OK) { 3874 pkiDebug("C_Sign: %s\n", pkinit_pkcs11_code_to_text(r)); 3875 return KRB5KDC_ERR_PREAUTH_FAILED; 3876 } 3877 pkiDebug("sign %d -> %d\n", (int) data_len, (int) len); 3878 *sig_len = len; 3879 *sig = cp; 3880 3881 return 0; 3882 } 3883 #endif 3884 3885 krb5_error_code 3886 pkinit_sign_data(krb5_context context, 3887 pkinit_identity_crypto_context id_cryptoctx, 3888 unsigned char *data, 3889 unsigned int data_len, 3890 unsigned char **sig, 3891 unsigned int *sig_len) 3892 { 3893 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; 3894 3895 if (id_cryptoctx == NULL || id_cryptoctx->pkcs11_method != 1) 3896 retval = pkinit_sign_data_fs(context, id_cryptoctx, data, data_len, 3897 sig, sig_len); 3898 #ifndef WITHOUT_PKCS11 3899 else 3900 retval = pkinit_sign_data_pkcs11(context, id_cryptoctx, data, data_len, 3901 sig, sig_len); 3902 #endif 3903 3904 return retval; 3905 } 3906 3907 3908 static krb5_error_code 3909 decode_data(unsigned char **out_data, unsigned int *out_data_len, 3910 unsigned char *data, unsigned int data_len, 3911 EVP_PKEY *pkey, X509 *cert) 3912 { 3913 /* Solaris Kerberos */ 3914 int len; 3915 unsigned char *buf = NULL; 3916 int buf_len = 0; 3917 3918 /* Solaris Kerberos */ 3919 if (out_data == NULL || out_data_len == NULL) 3920 return EINVAL; 3921 3922 if (cert && !X509_check_private_key(cert, pkey)) { 3923 pkiDebug("private key does not match certificate\n"); 3924 /* Solaris Kerberos */ 3925 return EINVAL; 3926 } 3927 3928 buf_len = EVP_PKEY_size(pkey); 3929 buf = (unsigned char *)malloc((size_t) buf_len + 10); 3930 if (buf == NULL) 3931 return ENOMEM; 3932 3933 len = EVP_PKEY_decrypt(buf, data, (int)data_len, pkey); 3934 if (len <= 0) { 3935 pkiDebug("unable to decrypt received data (len=%d)\n", data_len); 3936 /* Solaris Kerberos */ 3937 free(buf); 3938 return KRB5KRB_ERR_GENERIC; 3939 } 3940 *out_data = buf; 3941 *out_data_len = len; 3942 3943 return 0; 3944 } 3945 3946 static krb5_error_code 3947 create_signature(unsigned char **sig, unsigned int *sig_len, 3948 unsigned char *data, unsigned int data_len, EVP_PKEY *pkey) 3949 { 3950 krb5_error_code retval = ENOMEM; 3951 EVP_MD_CTX md_ctx; 3952 3953 if (pkey == NULL) 3954 /* Solaris Kerberos */ 3955 return EINVAL; 3956 3957 EVP_VerifyInit(&md_ctx, EVP_sha1()); 3958 EVP_SignUpdate(&md_ctx, data, data_len); 3959 *sig_len = EVP_PKEY_size(pkey); 3960 if ((*sig = (unsigned char *) malloc((size_t) *sig_len)) == NULL) 3961 goto cleanup; 3962 EVP_SignFinal(&md_ctx, *sig, sig_len, pkey); 3963 3964 retval = 0; 3965 3966 cleanup: 3967 EVP_MD_CTX_cleanup(&md_ctx); 3968 3969 return retval; 3970 } 3971 3972 /* 3973 * Note: 3974 * This is not the routine the KDC uses to get its certificate. 3975 * This routine is intended to be called by the client 3976 * to obtain the KDC's certificate from some local storage 3977 * to be sent as a hint in its request to the KDC. 3978 */ 3979 /* ARGSUSED */ 3980 krb5_error_code 3981 pkinit_get_kdc_cert(krb5_context context, 3982 pkinit_plg_crypto_context plg_cryptoctx, 3983 pkinit_req_crypto_context req_cryptoctx, 3984 pkinit_identity_crypto_context id_cryptoctx, 3985 krb5_principal princ) 3986 { 3987 /* Solaris Kerberos */ 3988 if (req_cryptoctx == NULL) 3989 return EINVAL; 3990 3991 req_cryptoctx->received_cert = NULL; 3992 return 0; 3993 } 3994 3995 /* ARGSUSED */ 3996 static krb5_error_code 3997 pkinit_get_certs_pkcs12(krb5_context context, 3998 pkinit_plg_crypto_context plg_cryptoctx, 3999 pkinit_req_crypto_context req_cryptoctx, 4000 pkinit_identity_opts *idopts, 4001 pkinit_identity_crypto_context id_cryptoctx, 4002 krb5_principal princ) 4003 { 4004 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; 4005 X509 *x = NULL; 4006 PKCS12 *p12 = NULL; 4007 int ret; 4008 FILE *fp; 4009 EVP_PKEY *y = NULL; 4010 4011 if (idopts->cert_filename == NULL) { 4012 /* Solaris Kerberos: Improved error messages */ 4013 krb5_set_error_message(context, retval, 4014 gettext("failed to get certificate location")); 4015 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__); 4016 goto cleanup; 4017 } 4018 4019 if (idopts->key_filename == NULL) { 4020 /* Solaris Kerberos: Improved error messages */ 4021 krb5_set_error_message(context, retval, 4022 gettext("failed to get private key location")); 4023 pkiDebug("%s: failed to get user's private key location\n", __FUNCTION__); 4024 goto cleanup; 4025 } 4026 4027 fp = fopen(idopts->cert_filename, "rb"); 4028 if (fp == NULL) { 4029 /* Solaris Kerberos: Improved error messages */ 4030 krb5_set_error_message(context, retval, 4031 gettext("failed to open PKCS12 file '%s': %s"), 4032 idopts->cert_filename, error_message(errno)); 4033 pkiDebug("Failed to open PKCS12 file '%s', error %d\n", 4034 idopts->cert_filename, errno); 4035 goto cleanup; 4036 } 4037 4038 p12 = d2i_PKCS12_fp(fp, NULL); 4039 (void) fclose(fp); 4040 if (p12 == NULL) { 4041 krb5_set_error_message(context, retval, 4042 gettext("failed to decode PKCS12 file '%s' contents"), 4043 idopts->cert_filename); 4044 pkiDebug("Failed to decode PKCS12 file '%s' contents\n", 4045 idopts->cert_filename); 4046 goto cleanup; 4047 } 4048 /* 4049 * Try parsing with no pass phrase first. If that fails, 4050 * prompt for the pass phrase and try again. 4051 */ 4052 ret = PKCS12_parse(p12, NULL, &y, &x, NULL); 4053 if (ret == 0) { 4054 krb5_data rdat; 4055 krb5_prompt kprompt; 4056 krb5_prompt_type prompt_type; 4057 int r = 0; 4058 char prompt_string[128]; 4059 char prompt_reply[128]; 4060 /* Solaris Kerberos */ 4061 char *prompt_prefix = gettext("Pass phrase for"); 4062 4063 pkiDebug("Initial PKCS12_parse with no password failed\n"); 4064 4065 (void) memset(prompt_reply, '\0', sizeof(prompt_reply)); 4066 rdat.data = prompt_reply; 4067 rdat.length = sizeof(prompt_reply); 4068 4069 r = snprintf(prompt_string, sizeof(prompt_string), "%s %s", 4070 prompt_prefix, idopts->cert_filename); 4071 if (r >= sizeof(prompt_string)) { 4072 pkiDebug("Prompt string, '%s %s', is too long!\n", 4073 prompt_prefix, idopts->cert_filename); 4074 goto cleanup; 4075 } 4076 kprompt.prompt = prompt_string; 4077 kprompt.hidden = 1; 4078 kprompt.reply = &rdat; 4079 prompt_type = KRB5_PROMPT_TYPE_PREAUTH; 4080 4081 /* PROMPTER_INVOCATION */ 4082 k5int_set_prompt_types(context, &prompt_type); 4083 r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data, 4084 NULL, NULL, 1, &kprompt); 4085 k5int_set_prompt_types(context, 0); 4086 4087 ret = PKCS12_parse(p12, rdat.data, &y, &x, NULL); 4088 if (ret == 0) { 4089 /* Solaris Kerberos: Improved error messages */ 4090 krb5_set_error_message(context, retval, 4091 gettext("failed to parse PKCS12 file '%s' with password"), 4092 idopts->cert_filename); 4093 pkiDebug("Seconde PKCS12_parse with password failed\n"); 4094 goto cleanup; 4095 } 4096 } 4097 id_cryptoctx->creds[0] = malloc(sizeof(struct _pkinit_cred_info)); 4098 if (id_cryptoctx->creds[0] == NULL) 4099 goto cleanup; 4100 id_cryptoctx->creds[0]->cert = x; 4101 #ifndef WITHOUT_PKCS11 4102 id_cryptoctx->creds[0]->cert_id = NULL; 4103 id_cryptoctx->creds[0]->cert_id_len = 0; 4104 #endif 4105 id_cryptoctx->creds[0]->key = y; 4106 id_cryptoctx->creds[1] = NULL; 4107 4108 retval = 0; 4109 4110 cleanup: 4111 if (p12) 4112 PKCS12_free(p12); 4113 if (retval) { 4114 if (x != NULL) 4115 X509_free(x); 4116 if (y != NULL) 4117 EVP_PKEY_free(y); 4118 } 4119 return retval; 4120 } 4121 4122 static krb5_error_code 4123 pkinit_load_fs_cert_and_key(krb5_context context, 4124 pkinit_identity_crypto_context id_cryptoctx, 4125 char *certname, 4126 char *keyname, 4127 int cindex) 4128 { 4129 krb5_error_code retval; 4130 X509 *x = NULL; 4131 EVP_PKEY *y = NULL; 4132 4133 /* load the certificate */ 4134 retval = get_cert(certname, &x); 4135 if (retval != 0 || x == NULL) { 4136 /* Solaris Kerberos: Improved error messages */ 4137 krb5_set_error_message(context, retval, 4138 gettext("failed to load user's certificate from %s: %s"), 4139 certname, error_message(retval)); 4140 pkiDebug("failed to load user's certificate from '%s'\n", certname); 4141 goto cleanup; 4142 } 4143 retval = get_key(keyname, &y); 4144 if (retval != 0 || y == NULL) { 4145 /* Solaris Kerberos: Improved error messages */ 4146 krb5_set_error_message(context, retval, 4147 gettext("failed to load user's private key from %s: %s"), 4148 keyname, error_message(retval)); 4149 pkiDebug("failed to load user's private key from '%s'\n", keyname); 4150 goto cleanup; 4151 } 4152 4153 id_cryptoctx->creds[cindex] = malloc(sizeof(struct _pkinit_cred_info)); 4154 if (id_cryptoctx->creds[cindex] == NULL) { 4155 retval = ENOMEM; 4156 goto cleanup; 4157 } 4158 id_cryptoctx->creds[cindex]->cert = x; 4159 #ifndef WITHOUT_PKCS11 4160 id_cryptoctx->creds[cindex]->cert_id = NULL; 4161 id_cryptoctx->creds[cindex]->cert_id_len = 0; 4162 #endif 4163 id_cryptoctx->creds[cindex]->key = y; 4164 id_cryptoctx->creds[cindex+1] = NULL; 4165 4166 retval = 0; 4167 4168 cleanup: 4169 if (retval) { 4170 if (x != NULL) 4171 X509_free(x); 4172 if (y != NULL) 4173 EVP_PKEY_free(y); 4174 } 4175 return retval; 4176 } 4177 4178 /* ARGSUSED */ 4179 static krb5_error_code 4180 pkinit_get_certs_fs(krb5_context context, 4181 pkinit_plg_crypto_context plg_cryptoctx, 4182 pkinit_req_crypto_context req_cryptoctx, 4183 pkinit_identity_opts *idopts, 4184 pkinit_identity_crypto_context id_cryptoctx, 4185 krb5_principal princ) 4186 { 4187 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; 4188 4189 if (idopts->cert_filename == NULL) { 4190 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__); 4191 goto cleanup; 4192 } 4193 4194 if (idopts->key_filename == NULL) { 4195 pkiDebug("%s: failed to get user's private key location\n", 4196 __FUNCTION__); 4197 goto cleanup; 4198 } 4199 4200 retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx, 4201 idopts->cert_filename, 4202 idopts->key_filename, 0); 4203 cleanup: 4204 return retval; 4205 } 4206 4207 /* ARGSUSED */ 4208 static krb5_error_code 4209 pkinit_get_certs_dir(krb5_context context, 4210 pkinit_plg_crypto_context plg_cryptoctx, 4211 pkinit_req_crypto_context req_cryptoctx, 4212 pkinit_identity_opts *idopts, 4213 pkinit_identity_crypto_context id_cryptoctx, 4214 krb5_principal princ) 4215 { 4216 /* Solaris Kerberos */ 4217 krb5_error_code retval = KRB5KRB_ERR_GENERIC; 4218 DIR *d = NULL; 4219 struct dirent *dentry = NULL; 4220 char certname[1024]; 4221 char keyname[1024]; 4222 int i = 0, len; 4223 char *dirname, *suf; 4224 4225 /* Solaris Kerberos */ 4226 if (idopts == NULL) 4227 return EINVAL; 4228 4229 if (idopts->cert_filename == NULL) { 4230 pkiDebug("%s: failed to get user's certificate directory location\n", 4231 __FUNCTION__); 4232 return ENOENT; 4233 } 4234 4235 dirname = idopts->cert_filename; 4236 d = opendir(dirname); 4237 if (d == NULL) { 4238 /* Solaris Kerberos: Improved error messages */ 4239 krb5_set_error_message(context, errno, 4240 gettext("failed to open directory \"%s\": %s"), 4241 dirname, error_message(errno)); 4242 return errno; 4243 } 4244 4245 /* 4246 * We'll assume that certs are named XXX.crt and the corresponding 4247 * key is named XXX.key 4248 */ 4249 while ((i < MAX_CREDS_ALLOWED) && (dentry = readdir(d)) != NULL) { 4250 /* Ignore subdirectories and anything starting with a dot */ 4251 #ifdef DT_DIR 4252 if (dentry->d_type == DT_DIR) 4253 continue; 4254 #endif 4255 if (dentry->d_name[0] == '.') 4256 continue; 4257 len = strlen(dentry->d_name); 4258 if (len < 5) 4259 continue; 4260 suf = dentry->d_name + (len - 4); 4261 if (strncmp(suf, ".crt", 4) != 0) 4262 continue; 4263 4264 /* Checked length */ 4265 if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(certname)) { 4266 pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n", 4267 __FUNCTION__, dirname, dentry->d_name); 4268 continue; 4269 } 4270 (void) snprintf(certname, sizeof(certname), "%s/%s", dirname, dentry->d_name); 4271 (void) snprintf(keyname, sizeof(keyname), "%s/%s", dirname, dentry->d_name); 4272 len = strlen(keyname); 4273 keyname[len - 3] = 'k'; 4274 keyname[len - 2] = 'e'; 4275 keyname[len - 1] = 'y'; 4276 4277 retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx, 4278 certname, keyname, i); 4279 if (retval == 0) { 4280 pkiDebug("%s: Successfully loaded cert (and key) for %s\n", 4281 __FUNCTION__, dentry->d_name); 4282 i++; 4283 } 4284 else 4285 continue; 4286 } 4287 4288 if (i == 0) { 4289 /* Solaris Kerberos: Improved error messages */ 4290 krb5_set_error_message(context, ENOENT, 4291 gettext("No suitable cert/key pairs found in directory '%s'"), 4292 idopts->cert_filename); 4293 pkiDebug("%s: No cert/key pairs found in directory '%s'\n", 4294 __FUNCTION__, idopts->cert_filename); 4295 retval = ENOENT; 4296 goto cleanup; 4297 } 4298 4299 retval = 0; 4300 4301 cleanup: 4302 if (d) 4303 (void) closedir(d); 4304 4305 return retval; 4306 } 4307 4308 #ifndef WITHOUT_PKCS11 4309 /* ARGSUSED */ 4310 static krb5_error_code 4311 pkinit_get_certs_pkcs11(krb5_context context, 4312 pkinit_plg_crypto_context plg_cryptoctx, 4313 pkinit_req_crypto_context req_cryptoctx, 4314 pkinit_identity_opts *idopts, 4315 pkinit_identity_crypto_context id_cryptoctx, 4316 krb5_principal princ) 4317 { 4318 #ifdef PKINIT_USE_MECH_LIST 4319 CK_MECHANISM_TYPE_PTR mechp; 4320 CK_MECHANISM_INFO info; 4321 #endif 4322 CK_OBJECT_CLASS cls; 4323 CK_OBJECT_HANDLE obj; 4324 CK_ATTRIBUTE attrs[4]; 4325 CK_ULONG count; 4326 CK_CERTIFICATE_TYPE certtype; 4327 CK_BYTE_PTR cert = NULL, cert_id; 4328 const unsigned char *cp; 4329 int i, r; 4330 unsigned int nattrs; 4331 X509 *x = NULL; 4332 4333 /* Copy stuff from idopts -> id_cryptoctx */ 4334 if (idopts->p11_module_name != NULL) { 4335 id_cryptoctx->p11_module_name = strdup(idopts->p11_module_name); 4336 if (id_cryptoctx->p11_module_name == NULL) 4337 return ENOMEM; 4338 } 4339 if (idopts->token_label != NULL) { 4340 id_cryptoctx->token_label = strdup(idopts->token_label); 4341 if (id_cryptoctx->token_label == NULL) 4342 return ENOMEM; 4343 } 4344 if (idopts->cert_label != NULL) { 4345 id_cryptoctx->cert_label = strdup(idopts->cert_label); 4346 if (id_cryptoctx->cert_label == NULL) 4347 return ENOMEM; 4348 } 4349 /* Convert the ascii cert_id string into a binary blob */ 4350 /* 4351 * Solaris Kerberos: 4352 * If the cert_id_string is empty then behave in a similar way to how 4353 * an empty certlabel is treated - i.e. don't fail now but rather continue 4354 * as though the certid wasn't specified. 4355 */ 4356 if (idopts->cert_id_string != NULL && strlen(idopts->cert_id_string) != 0) { 4357 BIGNUM *bn = NULL; 4358 BN_hex2bn(&bn, idopts->cert_id_string); 4359 if (bn == NULL) 4360 return ENOMEM; 4361 id_cryptoctx->cert_id_len = BN_num_bytes(bn); 4362 id_cryptoctx->cert_id = malloc((size_t) id_cryptoctx->cert_id_len); 4363 if (id_cryptoctx->cert_id == NULL) { 4364 BN_free(bn); 4365 return ENOMEM; 4366 } 4367 BN_bn2bin(bn, id_cryptoctx->cert_id); 4368 BN_free(bn); 4369 } 4370 id_cryptoctx->slotid = idopts->slotid; 4371 id_cryptoctx->pkcs11_method = 1; 4372 4373 4374 4375 if (pkinit_open_session(context, id_cryptoctx)) { 4376 pkiDebug("can't open pkcs11 session\n"); 4377 return KRB5KDC_ERR_PREAUTH_FAILED; 4378 } 4379 4380 #ifndef PKINIT_USE_MECH_LIST 4381 /* 4382 * We'd like to use CKM_SHA1_RSA_PKCS for signing if it's available, but 4383 * many cards seems to be confused about whether they are capable of 4384 * this or not. The safe thing seems to be to ignore the mechanism list, 4385 * always use CKM_RSA_PKCS and calculate the sha1 digest ourselves. 4386 */ 4387 4388 id_cryptoctx->mech = CKM_RSA_PKCS; 4389 #else 4390 if ((r = id_cryptoctx->p11->C_GetMechanismList(id_cryptoctx->slotid, NULL, 4391 &count)) != CKR_OK || count <= 0) { 4392 pkiDebug("C_GetMechanismList: %s\n", pkinit_pkcs11_code_to_text(r)); 4393 return KRB5KDC_ERR_PREAUTH_FAILED; 4394 } 4395 mechp = (CK_MECHANISM_TYPE_PTR) malloc(count * sizeof (CK_MECHANISM_TYPE)); 4396 if (mechp == NULL) 4397 return ENOMEM; 4398 if ((r = id_cryptoctx->p11->C_GetMechanismList(id_cryptoctx->slotid, 4399 mechp, &count)) != CKR_OK) 4400 return KRB5KDC_ERR_PREAUTH_FAILED; 4401 for (i = 0; i < count; i++) { 4402 if ((r = id_cryptoctx->p11->C_GetMechanismInfo(id_cryptoctx->slotid, 4403 mechp[i], &info)) != CKR_OK) 4404 return KRB5KDC_ERR_PREAUTH_FAILED; 4405 #ifdef DEBUG_MECHINFO 4406 pkiDebug("mech %x flags %x\n", (int) mechp[i], (int) info.flags); 4407 if ((info.flags & (CKF_SIGN|CKF_DECRYPT)) == (CKF_SIGN|CKF_DECRYPT)) 4408 pkiDebug(" this mech is good for sign & decrypt\n"); 4409 #endif 4410 if (mechp[i] == CKM_RSA_PKCS) { 4411 /* This seems backwards... */ 4412 id_cryptoctx->mech = 4413 (info.flags & CKF_SIGN) ? CKM_SHA1_RSA_PKCS : CKM_RSA_PKCS; 4414 } 4415 } 4416 free(mechp); 4417 4418 pkiDebug("got %d mechs from card\n", (int) count); 4419 #endif 4420 4421 cls = CKO_CERTIFICATE; 4422 attrs[0].type = CKA_CLASS; 4423 attrs[0].pValue = &cls; 4424 attrs[0].ulValueLen = sizeof cls; 4425 4426 certtype = CKC_X_509; 4427 attrs[1].type = CKA_CERTIFICATE_TYPE; 4428 attrs[1].pValue = &certtype; 4429 attrs[1].ulValueLen = sizeof certtype; 4430 4431 nattrs = 2; 4432 4433 /* If a cert id and/or label were given, use them too */ 4434 if (id_cryptoctx->cert_id_len > 0) { 4435 attrs[nattrs].type = CKA_ID; 4436 attrs[nattrs].pValue = id_cryptoctx->cert_id; 4437 attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len; 4438 nattrs++; 4439 } 4440 if (id_cryptoctx->cert_label != NULL) { 4441 attrs[nattrs].type = CKA_LABEL; 4442 attrs[nattrs].pValue = id_cryptoctx->cert_label; 4443 attrs[nattrs].ulValueLen = strlen(id_cryptoctx->cert_label); 4444 nattrs++; 4445 } 4446 4447 r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs); 4448 if (r != CKR_OK) { 4449 pkiDebug("C_FindObjectsInit: %s\n", pkinit_pkcs11_code_to_text(r)); 4450 return KRB5KDC_ERR_PREAUTH_FAILED; 4451 } 4452 4453 for (i = 0; ; i++) { 4454 if (i >= MAX_CREDS_ALLOWED) 4455 return KRB5KDC_ERR_PREAUTH_FAILED; 4456 4457 /* Look for x.509 cert */ 4458 /* Solaris Kerberos */ 4459 if ((r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, 4460 &obj, 1, &count)) != CKR_OK || count == 0) { 4461 id_cryptoctx->creds[i] = NULL; 4462 break; 4463 } 4464 4465 /* Get cert and id len */ 4466 attrs[0].type = CKA_VALUE; 4467 attrs[0].pValue = NULL; 4468 attrs[0].ulValueLen = 0; 4469 4470 attrs[1].type = CKA_ID; 4471 attrs[1].pValue = NULL; 4472 attrs[1].ulValueLen = 0; 4473 4474 if ((r = id_cryptoctx->p11->C_GetAttributeValue(id_cryptoctx->session, 4475 obj, attrs, 2)) != CKR_OK && r != CKR_BUFFER_TOO_SMALL) { 4476 pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r)); 4477 return KRB5KDC_ERR_PREAUTH_FAILED; 4478 } 4479 cert = (CK_BYTE_PTR) malloc((size_t) attrs[0].ulValueLen + 1); 4480 cert_id = (CK_BYTE_PTR) malloc((size_t) attrs[1].ulValueLen + 1); 4481 if (cert == NULL || cert_id == NULL) 4482 return ENOMEM; 4483 4484 /* Read the cert and id off the card */ 4485 4486 attrs[0].type = CKA_VALUE; 4487 attrs[0].pValue = cert; 4488 4489 attrs[1].type = CKA_ID; 4490 attrs[1].pValue = cert_id; 4491 4492 if ((r = id_cryptoctx->p11->C_GetAttributeValue(id_cryptoctx->session, 4493 obj, attrs, 2)) != CKR_OK) { 4494 pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r)); 4495 return KRB5KDC_ERR_PREAUTH_FAILED; 4496 } 4497 4498 pkiDebug("cert %d size %d id %d idlen %d\n", i, 4499 (int) attrs[0].ulValueLen, (int) cert_id[0], 4500 (int) attrs[1].ulValueLen); 4501 4502 cp = (unsigned char *) cert; 4503 x = d2i_X509(NULL, &cp, (int) attrs[0].ulValueLen); 4504 if (x == NULL) 4505 return KRB5KDC_ERR_PREAUTH_FAILED; 4506 id_cryptoctx->creds[i] = malloc(sizeof(struct _pkinit_cred_info)); 4507 if (id_cryptoctx->creds[i] == NULL) 4508 return KRB5KDC_ERR_PREAUTH_FAILED; 4509 id_cryptoctx->creds[i]->cert = x; 4510 id_cryptoctx->creds[i]->key = NULL; 4511 id_cryptoctx->creds[i]->cert_id = cert_id; 4512 id_cryptoctx->creds[i]->cert_id_len = attrs[1].ulValueLen; 4513 free(cert); 4514 } 4515 id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session); 4516 /* Solaris Kerberos: Improved error messages */ 4517 if (cert == NULL) { 4518 if (r != CKR_OK) { 4519 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, 4520 gettext("pkcs11 error while searching for certificates: %s"), 4521 pkinit_pkcs11_code_to_text(r)); 4522 } else { 4523 BIGNUM *cid = BN_bin2bn(id_cryptoctx->cert_id, 4524 id_cryptoctx->cert_id_len, NULL); 4525 char *cidstr = BN_bn2hex(cid); 4526 char *printstr = id_cryptoctx->cert_id_len ? cidstr : "<none>"; 4527 4528 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, 4529 gettext("failed to find any suitable certificates " 4530 "(certlabel: %s, certid: %s)"), 4531 id_cryptoctx->cert_label ? id_cryptoctx->cert_label : "<none>", 4532 cidstr ? printstr : "<unknown>"); 4533 4534 if (cidstr != NULL) 4535 OPENSSL_free(cidstr); 4536 BN_free(cid); 4537 } 4538 return KRB5KDC_ERR_PREAUTH_FAILED; 4539 } 4540 return 0; 4541 } 4542 #endif 4543 4544 /* ARGSUSED */ 4545 static void 4546 free_cred_info(krb5_context context, 4547 pkinit_identity_crypto_context id_cryptoctx, 4548 struct _pkinit_cred_info *cred) 4549 { 4550 if (cred != NULL) { 4551 if (cred->cert != NULL) 4552 X509_free(cred->cert); 4553 if (cred->key != NULL) 4554 EVP_PKEY_free(cred->key); 4555 #ifndef WITHOUT_PKCS11 4556 if (cred->cert_id != NULL) 4557 free(cred->cert_id); 4558 #endif 4559 free(cred); 4560 } 4561 } 4562 4563 /* ARGSUSED */ 4564 krb5_error_code 4565 crypto_free_cert_info(krb5_context context, 4566 pkinit_plg_crypto_context plg_cryptoctx, 4567 pkinit_req_crypto_context req_cryptoctx, 4568 pkinit_identity_crypto_context id_cryptoctx) 4569 { 4570 int i; 4571 4572 if (id_cryptoctx == NULL) 4573 return EINVAL; 4574 4575 for (i = 0; i < MAX_CREDS_ALLOWED; i++) { 4576 if (id_cryptoctx->creds[i] != NULL) { 4577 free_cred_info(context, id_cryptoctx, id_cryptoctx->creds[i]); 4578 id_cryptoctx->creds[i] = NULL; 4579 } 4580 } 4581 return 0; 4582 } 4583 4584 krb5_error_code 4585 crypto_load_certs(krb5_context context, 4586 pkinit_plg_crypto_context plg_cryptoctx, 4587 pkinit_req_crypto_context req_cryptoctx, 4588 pkinit_identity_opts *idopts, 4589 pkinit_identity_crypto_context id_cryptoctx, 4590 krb5_principal princ) 4591 { 4592 krb5_error_code retval; 4593 4594 switch(idopts->idtype) { 4595 case IDTYPE_FILE: 4596 retval = pkinit_get_certs_fs(context, plg_cryptoctx, 4597 req_cryptoctx, idopts, 4598 id_cryptoctx, princ); 4599 break; 4600 case IDTYPE_DIR: 4601 retval = pkinit_get_certs_dir(context, plg_cryptoctx, 4602 req_cryptoctx, idopts, 4603 id_cryptoctx, princ); 4604 break; 4605 #ifndef WITHOUT_PKCS11 4606 case IDTYPE_PKCS11: 4607 retval = pkinit_get_certs_pkcs11(context, plg_cryptoctx, 4608 req_cryptoctx, idopts, 4609 id_cryptoctx, princ); 4610 break; 4611 #endif 4612 case IDTYPE_PKCS12: 4613 retval = pkinit_get_certs_pkcs12(context, plg_cryptoctx, 4614 req_cryptoctx, idopts, 4615 id_cryptoctx, princ); 4616 break; 4617 default: 4618 retval = EINVAL; 4619 } 4620 /* Solaris Kerberos */ 4621 4622 return retval; 4623 } 4624 4625 /* 4626 * Get number of certificates available after crypto_load_certs() 4627 */ 4628 /* ARGSUSED */ 4629 krb5_error_code 4630 crypto_cert_get_count(krb5_context context, 4631 pkinit_plg_crypto_context plg_cryptoctx, 4632 pkinit_req_crypto_context req_cryptoctx, 4633 pkinit_identity_crypto_context id_cryptoctx, 4634 int *cert_count) 4635 { 4636 int count; 4637 4638 if (id_cryptoctx == NULL || id_cryptoctx->creds[0] == NULL) 4639 return EINVAL; 4640 4641 for (count = 0; 4642 count <= MAX_CREDS_ALLOWED && id_cryptoctx->creds[count] != NULL; 4643 count++); 4644 *cert_count = count; 4645 return 0; 4646 } 4647 4648 4649 /* 4650 * Begin iteration over the certs loaded in crypto_load_certs() 4651 */ 4652 /* ARGSUSED */ 4653 krb5_error_code 4654 crypto_cert_iteration_begin(krb5_context context, 4655 pkinit_plg_crypto_context plg_cryptoctx, 4656 pkinit_req_crypto_context req_cryptoctx, 4657 pkinit_identity_crypto_context id_cryptoctx, 4658 pkinit_cert_iter_handle *ih_ret) 4659 { 4660 struct _pkinit_cert_iter_data *id; 4661 4662 if (id_cryptoctx == NULL || ih_ret == NULL) 4663 return EINVAL; 4664 if (id_cryptoctx->creds[0] == NULL) /* No cred info available */ 4665 return ENOENT; 4666 4667 id = calloc(1, sizeof(*id)); 4668 if (id == NULL) 4669 return ENOMEM; 4670 id->magic = ITER_MAGIC; 4671 id->plgctx = plg_cryptoctx, 4672 id->reqctx = req_cryptoctx, 4673 id->idctx = id_cryptoctx; 4674 id->index = 0; 4675 *ih_ret = (pkinit_cert_iter_handle) id; 4676 return 0; 4677 } 4678 4679 /* 4680 * End iteration over the certs loaded in crypto_load_certs() 4681 */ 4682 /* ARGSUSED */ 4683 krb5_error_code 4684 crypto_cert_iteration_end(krb5_context context, 4685 pkinit_cert_iter_handle ih) 4686 { 4687 struct _pkinit_cert_iter_data *id = (struct _pkinit_cert_iter_data *)ih; 4688 4689 if (id == NULL || id->magic != ITER_MAGIC) 4690 return EINVAL; 4691 free(ih); 4692 return 0; 4693 } 4694 4695 /* 4696 * Get next certificate handle 4697 */ 4698 /* ARGSUSED */ 4699 krb5_error_code 4700 crypto_cert_iteration_next(krb5_context context, 4701 pkinit_cert_iter_handle ih, 4702 pkinit_cert_handle *ch_ret) 4703 { 4704 struct _pkinit_cert_iter_data *id = (struct _pkinit_cert_iter_data *)ih; 4705 struct _pkinit_cert_data *cd; 4706 pkinit_identity_crypto_context id_cryptoctx; 4707 4708 if (id == NULL || id->magic != ITER_MAGIC) 4709 return EINVAL; 4710 4711 if (ch_ret == NULL) 4712 return EINVAL; 4713 4714 id_cryptoctx = id->idctx; 4715 if (id_cryptoctx == NULL) 4716 return EINVAL; 4717 4718 if (id_cryptoctx->creds[id->index] == NULL) 4719 return PKINIT_ITER_NO_MORE; 4720 4721 cd = calloc(1, sizeof(*cd)); 4722 if (cd == NULL) 4723 return ENOMEM; 4724 4725 cd->magic = CERT_MAGIC; 4726 cd->plgctx = id->plgctx; 4727 cd->reqctx = id->reqctx; 4728 cd->idctx = id->idctx; 4729 cd->index = id->index; 4730 cd->cred = id_cryptoctx->creds[id->index++]; 4731 *ch_ret = (pkinit_cert_handle)cd; 4732 return 0; 4733 } 4734 4735 /* 4736 * Release cert handle 4737 */ 4738 /* ARGSUSED */ 4739 krb5_error_code 4740 crypto_cert_release(krb5_context context, 4741 pkinit_cert_handle ch) 4742 { 4743 struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch; 4744 if (cd == NULL || cd->magic != CERT_MAGIC) 4745 return EINVAL; 4746 free(cd); 4747 return 0; 4748 } 4749 4750 /* 4751 * Get certificate Key Usage and Extended Key Usage 4752 */ 4753 /* ARGSUSED */ 4754 static krb5_error_code 4755 crypto_retieve_X509_key_usage(krb5_context context, 4756 pkinit_plg_crypto_context plgcctx, 4757 pkinit_req_crypto_context reqcctx, 4758 X509 *x, 4759 unsigned int *ret_ku_bits, 4760 unsigned int *ret_eku_bits) 4761 { 4762 /* Solaris Kerberos */ 4763 int i; 4764 unsigned int eku_bits = 0, ku_bits = 0; 4765 ASN1_BIT_STRING *usage = NULL; 4766 4767 if (ret_ku_bits == NULL && ret_eku_bits == NULL) 4768 return EINVAL; 4769 4770 if (ret_eku_bits) 4771 *ret_eku_bits = 0; 4772 else { 4773 pkiDebug("%s: EKUs not requested, not checking\n", __FUNCTION__); 4774 goto check_kus; 4775 } 4776 4777 /* Start with Extended Key usage */ 4778 i = X509_get_ext_by_NID(x, NID_ext_key_usage, -1); 4779 if (i >= 0) { 4780 EXTENDED_KEY_USAGE *eku; 4781 4782 eku = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL); 4783 if (eku) { 4784 for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) { 4785 ASN1_OBJECT *certoid; 4786 certoid = sk_ASN1_OBJECT_value(eku, i); 4787 if ((OBJ_cmp(certoid, plgcctx->id_pkinit_KPClientAuth)) == 0) 4788 eku_bits |= PKINIT_EKU_PKINIT; 4789 else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_ms_smartcard_login))) == 0) 4790 eku_bits |= PKINIT_EKU_MSSCLOGIN; 4791 else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_client_auth))) == 0) 4792 eku_bits |= PKINIT_EKU_CLIENTAUTH; 4793 else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_email_protect))) == 0) 4794 eku_bits |= PKINIT_EKU_EMAILPROTECTION; 4795 } 4796 EXTENDED_KEY_USAGE_free(eku); 4797 } 4798 } 4799 pkiDebug("%s: returning eku 0x%08x\n", __FUNCTION__, eku_bits); 4800 *ret_eku_bits = eku_bits; 4801 4802 check_kus: 4803 /* Now the Key Usage bits */ 4804 if (ret_ku_bits) 4805 *ret_ku_bits = 0; 4806 else { 4807 pkiDebug("%s: KUs not requested, not checking\n", __FUNCTION__); 4808 goto out; 4809 } 4810 4811 /* Make sure usage exists before checking bits */ 4812 usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL); 4813 if (usage) { 4814 if (!ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE)) 4815 ku_bits |= PKINIT_KU_DIGITALSIGNATURE; 4816 if (!ku_reject(x, X509v3_KU_KEY_ENCIPHERMENT)) 4817 ku_bits |= PKINIT_KU_KEYENCIPHERMENT; 4818 ASN1_BIT_STRING_free(usage); 4819 } 4820 4821 pkiDebug("%s: returning ku 0x%08x\n", __FUNCTION__, ku_bits); 4822 *ret_ku_bits = ku_bits; 4823 4824 out: 4825 return 0; 4826 } 4827 4828 /* 4829 * Return a string format of an X509_NAME in buf where 4830 * size is an in/out parameter. On input it is the size 4831 * of the buffer, and on output it is the actual length 4832 * of the name. 4833 * If buf is NULL, returns the length req'd to hold name 4834 */ 4835 static char * 4836 X509_NAME_oneline_ex(X509_NAME * a, 4837 char *buf, 4838 unsigned int *size, 4839 unsigned long flag) 4840 { 4841 BIO *out = NULL; 4842 4843 out = BIO_new(BIO_s_mem ()); 4844 if (X509_NAME_print_ex(out, a, 0, flag) > 0) { 4845 if (buf != NULL && *size > (int) BIO_number_written(out)) { 4846 (void) memset(buf, 0, *size); 4847 BIO_read(out, buf, (int) BIO_number_written(out)); 4848 } 4849 else { 4850 *size = BIO_number_written(out); 4851 } 4852 } 4853 BIO_free(out); 4854 return (buf); 4855 } 4856 4857 /* 4858 * Get certificate information 4859 */ 4860 krb5_error_code 4861 crypto_cert_get_matching_data(krb5_context context, 4862 pkinit_cert_handle ch, 4863 pkinit_cert_matching_data **ret_md) 4864 { 4865 krb5_error_code retval; 4866 pkinit_cert_matching_data *md; 4867 krb5_principal *pkinit_sans =NULL, *upn_sans = NULL; 4868 struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch; 4869 int i, j; 4870 char buf[DN_BUF_LEN]; 4871 unsigned int bufsize = sizeof(buf); 4872 4873 if (cd == NULL || cd->magic != CERT_MAGIC) 4874 return EINVAL; 4875 if (ret_md == NULL) 4876 return EINVAL; 4877 4878 md = calloc(1, sizeof(*md)); 4879 if (md == NULL) 4880 return ENOMEM; 4881 4882 md->ch = ch; 4883 4884 /* get the subject name (in rfc2253 format) */ 4885 X509_NAME_oneline_ex(X509_get_subject_name(cd->cred->cert), 4886 buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS); 4887 md->subject_dn = strdup(buf); 4888 if (md->subject_dn == NULL) { 4889 retval = ENOMEM; 4890 goto cleanup; 4891 } 4892 4893 /* get the issuer name (in rfc2253 format) */ 4894 X509_NAME_oneline_ex(X509_get_issuer_name(cd->cred->cert), 4895 buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS); 4896 md->issuer_dn = strdup(buf); 4897 if (md->issuer_dn == NULL) { 4898 retval = ENOMEM; 4899 goto cleanup; 4900 } 4901 4902 /* get the san data */ 4903 retval = crypto_retrieve_X509_sans(context, cd->plgctx, cd->reqctx, 4904 cd->cred->cert, &pkinit_sans, 4905 &upn_sans, NULL); 4906 if (retval) 4907 goto cleanup; 4908 4909 j = 0; 4910 if (pkinit_sans != NULL) { 4911 for (i = 0; pkinit_sans[i] != NULL; i++) 4912 j++; 4913 } 4914 if (upn_sans != NULL) { 4915 for (i = 0; upn_sans[i] != NULL; i++) 4916 j++; 4917 } 4918 if (j != 0) { 4919 md->sans = calloc((size_t)j+1, sizeof(*md->sans)); 4920 if (md->sans == NULL) { 4921 retval = ENOMEM; 4922 goto cleanup; 4923 } 4924 j = 0; 4925 if (pkinit_sans != NULL) { 4926 for (i = 0; pkinit_sans[i] != NULL; i++) 4927 md->sans[j++] = pkinit_sans[i]; 4928 free(pkinit_sans); 4929 } 4930 if (upn_sans != NULL) { 4931 for (i = 0; upn_sans[i] != NULL; i++) 4932 md->sans[j++] = upn_sans[i]; 4933 free(upn_sans); 4934 } 4935 md->sans[j] = NULL; 4936 } else 4937 md->sans = NULL; 4938 4939 /* get the KU and EKU data */ 4940 4941 retval = crypto_retieve_X509_key_usage(context, cd->plgctx, cd->reqctx, 4942 cd->cred->cert, 4943 &md->ku_bits, &md->eku_bits); 4944 if (retval) 4945 goto cleanup; 4946 4947 *ret_md = md; 4948 retval = 0; 4949 cleanup: 4950 if (retval) { 4951 if (md) 4952 crypto_cert_free_matching_data(context, md); 4953 } 4954 return retval; 4955 } 4956 4957 /* 4958 * Free certificate information 4959 */ 4960 krb5_error_code 4961 crypto_cert_free_matching_data(krb5_context context, 4962 pkinit_cert_matching_data *md) 4963 { 4964 krb5_principal p; 4965 int i; 4966 4967 if (md == NULL) 4968 return EINVAL; 4969 if (md->subject_dn) 4970 free(md->subject_dn); 4971 if (md->issuer_dn) 4972 free(md->issuer_dn); 4973 if (md->sans) { 4974 for (i = 0, p = md->sans[i]; p != NULL; p = md->sans[++i]) 4975 krb5_free_principal(context, p); 4976 free(md->sans); 4977 } 4978 free(md); 4979 return 0; 4980 } 4981 4982 /* 4983 * Make this matching certificate "the chosen one" 4984 */ 4985 /* ARGSUSED */ 4986 krb5_error_code 4987 crypto_cert_select(krb5_context context, 4988 pkinit_cert_matching_data *md) 4989 { 4990 struct _pkinit_cert_data *cd; 4991 if (md == NULL) 4992 return EINVAL; 4993 4994 cd = (struct _pkinit_cert_data *)md->ch; 4995 if (cd == NULL || cd->magic != CERT_MAGIC) 4996 return EINVAL; 4997 4998 /* copy the selected cert into our id_cryptoctx */ 4999 if (cd->idctx->my_certs != NULL) { 5000 sk_X509_pop_free(cd->idctx->my_certs, X509_free); 5001 } 5002 cd->idctx->my_certs = sk_X509_new_null(); 5003 sk_X509_push(cd->idctx->my_certs, cd->cred->cert); 5004 cd->idctx->creds[cd->index]->cert = NULL; /* Don't free it twice */ 5005 cd->idctx->cert_index = 0; 5006 5007 if (cd->idctx->pkcs11_method != 1) { 5008 cd->idctx->my_key = cd->cred->key; 5009 cd->idctx->creds[cd->index]->key = NULL; /* Don't free it twice */ 5010 } 5011 #ifndef WITHOUT_PKCS11 5012 else { 5013 cd->idctx->cert_id = cd->cred->cert_id; 5014 cd->idctx->creds[cd->index]->cert_id = NULL; /* Don't free it twice */ 5015 cd->idctx->cert_id_len = cd->cred->cert_id_len; 5016 } 5017 #endif 5018 return 0; 5019 } 5020 5021 /* 5022 * Choose the default certificate as "the chosen one" 5023 */ 5024 krb5_error_code 5025 crypto_cert_select_default(krb5_context context, 5026 pkinit_plg_crypto_context plg_cryptoctx, 5027 pkinit_req_crypto_context req_cryptoctx, 5028 pkinit_identity_crypto_context id_cryptoctx) 5029 { 5030 krb5_error_code retval; 5031 int cert_count = 0; 5032 5033 retval = crypto_cert_get_count(context, plg_cryptoctx, req_cryptoctx, 5034 id_cryptoctx, &cert_count); 5035 if (retval) { 5036 pkiDebug("%s: crypto_cert_get_count error %d, %s\n", 5037 __FUNCTION__, retval, error_message(retval)); 5038 goto errout; 5039 } 5040 if (cert_count != 1) { 5041 /* Solaris Kerberos: Improved error messages */ 5042 retval = EINVAL; 5043 krb5_set_error_message(context, retval, 5044 gettext("failed to select default certificate: " 5045 "found %d certs to choose from but there must be exactly one"), 5046 cert_count); 5047 pkiDebug("%s: ERROR: There are %d certs to choose from, " 5048 "but there must be exactly one.\n", 5049 __FUNCTION__, cert_count); 5050 goto errout; 5051 } 5052 /* copy the selected cert into our id_cryptoctx */ 5053 if (id_cryptoctx->my_certs != NULL) { 5054 sk_X509_pop_free(id_cryptoctx->my_certs, X509_free); 5055 } 5056 id_cryptoctx->my_certs = sk_X509_new_null(); 5057 sk_X509_push(id_cryptoctx->my_certs, id_cryptoctx->creds[0]->cert); 5058 id_cryptoctx->creds[0]->cert = NULL; /* Don't free it twice */ 5059 id_cryptoctx->cert_index = 0; 5060 5061 if (id_cryptoctx->pkcs11_method != 1) { 5062 id_cryptoctx->my_key = id_cryptoctx->creds[0]->key; 5063 id_cryptoctx->creds[0]->key = NULL; /* Don't free it twice */ 5064 } 5065 #ifndef WITHOUT_PKCS11 5066 else { 5067 id_cryptoctx->cert_id = id_cryptoctx->creds[0]->cert_id; 5068 id_cryptoctx->creds[0]->cert_id = NULL; /* Don't free it twice */ 5069 id_cryptoctx->cert_id_len = id_cryptoctx->creds[0]->cert_id_len; 5070 } 5071 #endif 5072 retval = 0; 5073 errout: 5074 return retval; 5075 } 5076 5077 5078 /* ARGSUSED */ 5079 static krb5_error_code 5080 load_cas_and_crls(krb5_context context, 5081 pkinit_plg_crypto_context plg_cryptoctx, 5082 pkinit_req_crypto_context req_cryptoctx, 5083 pkinit_identity_crypto_context id_cryptoctx, 5084 int catype, 5085 char *filename) 5086 { 5087 STACK_OF(X509_INFO) *sk = NULL; 5088 STACK_OF(X509) *ca_certs = NULL; 5089 STACK_OF(X509_CRL) *ca_crls = NULL; 5090 BIO *in = NULL; 5091 /* Solaris Kerberos */ 5092 krb5_error_code retval = KRB5KRB_ERR_GENERIC; 5093 int i = 0; 5094 5095 /* If there isn't already a stack in the context, 5096 * create a temporary one now */ 5097 switch(catype) { 5098 case CATYPE_ANCHORS: 5099 if (id_cryptoctx->trustedCAs != NULL) 5100 ca_certs = id_cryptoctx->trustedCAs; 5101 else { 5102 ca_certs = sk_X509_new_null(); 5103 if (ca_certs == NULL) 5104 return ENOMEM; 5105 } 5106 break; 5107 case CATYPE_INTERMEDIATES: 5108 if (id_cryptoctx->intermediateCAs != NULL) 5109 ca_certs = id_cryptoctx->intermediateCAs; 5110 else { 5111 ca_certs = sk_X509_new_null(); 5112 if (ca_certs == NULL) 5113 return ENOMEM; 5114 } 5115 break; 5116 case CATYPE_CRLS: 5117 if (id_cryptoctx->revoked != NULL) 5118 ca_crls = id_cryptoctx->revoked; 5119 else { 5120 ca_crls = sk_X509_CRL_new_null(); 5121 if (ca_crls == NULL) 5122 return ENOMEM; 5123 } 5124 break; 5125 default: 5126 return ENOTSUP; 5127 } 5128 5129 if (!(in = BIO_new_file(filename, "r"))) { 5130 retval = errno; 5131 pkiDebug("%s: error opening file '%s': %s\n", __FUNCTION__, 5132 filename, error_message(errno)); 5133 goto cleanup; 5134 } 5135 5136 /* This loads from a file, a stack of x509/crl/pkey sets */ 5137 if ((sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL)) == NULL) { 5138 pkiDebug("%s: error reading file '%s'\n", __FUNCTION__, filename); 5139 retval = EIO; 5140 goto cleanup; 5141 } 5142 5143 /* scan over the stack created from loading the file contents, 5144 * weed out duplicates, and push new ones onto the return stack 5145 */ 5146 for (i = 0; i < sk_X509_INFO_num(sk); i++) { 5147 X509_INFO *xi = sk_X509_INFO_value(sk, i); 5148 if (xi != NULL && xi->x509 != NULL && catype != CATYPE_CRLS) { 5149 int j = 0, size = sk_X509_num(ca_certs), flag = 0; 5150 5151 if (!size) { 5152 sk_X509_push(ca_certs, xi->x509); 5153 xi->x509 = NULL; 5154 continue; 5155 } 5156 for (j = 0; j < size; j++) { 5157 X509 *x = sk_X509_value(ca_certs, j); 5158 flag = X509_cmp(x, xi->x509); 5159 if (flag == 0) 5160 break; 5161 else 5162 continue; 5163 } 5164 if (flag != 0) { 5165 sk_X509_push(ca_certs, X509_dup(xi->x509)); 5166 } 5167 } else if (xi != NULL && xi->crl != NULL && catype == CATYPE_CRLS) { 5168 int j = 0, size = sk_X509_CRL_num(ca_crls), flag = 0; 5169 if (!size) { 5170 sk_X509_CRL_push(ca_crls, xi->crl); 5171 xi->crl = NULL; 5172 continue; 5173 } 5174 for (j = 0; j < size; j++) { 5175 X509_CRL *x = sk_X509_CRL_value(ca_crls, j); 5176 flag = X509_CRL_cmp(x, xi->crl); 5177 if (flag == 0) 5178 break; 5179 else 5180 continue; 5181 } 5182 if (flag != 0) { 5183 sk_X509_push(ca_crls, X509_CRL_dup(xi->crl)); 5184 } 5185 } 5186 } 5187 5188 /* If we added something and there wasn't a stack in the 5189 * context before, add the temporary stack to the context. 5190 */ 5191 switch(catype) { 5192 case CATYPE_ANCHORS: 5193 if (sk_X509_num(ca_certs) == 0) { 5194 pkiDebug("no anchors in file, %s\n", filename); 5195 if (id_cryptoctx->trustedCAs == NULL) 5196 sk_X509_free(ca_certs); 5197 } else { 5198 if (id_cryptoctx->trustedCAs == NULL) 5199 id_cryptoctx->trustedCAs = ca_certs; 5200 } 5201 break; 5202 case CATYPE_INTERMEDIATES: 5203 if (sk_X509_num(ca_certs) == 0) { 5204 pkiDebug("no intermediates in file, %s\n", filename); 5205 if (id_cryptoctx->intermediateCAs == NULL) 5206 sk_X509_free(ca_certs); 5207 } else { 5208 if (id_cryptoctx->intermediateCAs == NULL) 5209 id_cryptoctx->intermediateCAs = ca_certs; 5210 } 5211 break; 5212 case CATYPE_CRLS: 5213 if (sk_X509_num(ca_crls) == 0) { 5214 pkiDebug("no crls in file, %s\n", filename); 5215 if (id_cryptoctx->revoked == NULL) 5216 sk_X509_CRL_free(ca_crls); 5217 } else { 5218 if (id_cryptoctx->revoked == NULL) 5219 id_cryptoctx->revoked = ca_crls; 5220 } 5221 break; 5222 default: 5223 /* Should have been caught above! */ 5224 retval = EINVAL; 5225 goto cleanup; 5226 /* Solaris Kerberos: removed "break" as it's never reached */ 5227 } 5228 5229 retval = 0; 5230 5231 cleanup: 5232 if (in != NULL) 5233 BIO_free(in); 5234 if (sk != NULL) 5235 sk_X509_INFO_pop_free(sk, X509_INFO_free); 5236 5237 return retval; 5238 } 5239 5240 static krb5_error_code 5241 load_cas_and_crls_dir(krb5_context context, 5242 pkinit_plg_crypto_context plg_cryptoctx, 5243 pkinit_req_crypto_context req_cryptoctx, 5244 pkinit_identity_crypto_context id_cryptoctx, 5245 int catype, 5246 char *dirname) 5247 { 5248 krb5_error_code retval = EINVAL; 5249 DIR *d = NULL; 5250 struct dirent *dentry = NULL; 5251 char filename[1024]; 5252 5253 if (dirname == NULL) 5254 return EINVAL; 5255 5256 d = opendir(dirname); 5257 if (d == NULL) 5258 return ENOENT; 5259 5260 while ((dentry = readdir(d))) { 5261 if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(filename)) { 5262 pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n", 5263 __FUNCTION__, dirname, dentry->d_name); 5264 goto cleanup; 5265 } 5266 /* Ignore subdirectories and anything starting with a dot */ 5267 #ifdef DT_DIR 5268 if (dentry->d_type == DT_DIR) 5269 continue; 5270 #endif 5271 if (dentry->d_name[0] == '.') 5272 continue; 5273 (void) snprintf(filename, sizeof(filename), "%s/%s", dirname, dentry->d_name); 5274 5275 retval = load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx, 5276 id_cryptoctx, catype, filename); 5277 if (retval) 5278 goto cleanup; 5279 } 5280 5281 retval = 0; 5282 5283 cleanup: 5284 if (d != NULL) 5285 (void) closedir(d); 5286 5287 return retval; 5288 } 5289 5290 /* ARGSUSED */ 5291 krb5_error_code 5292 crypto_load_cas_and_crls(krb5_context context, 5293 pkinit_plg_crypto_context plg_cryptoctx, 5294 pkinit_req_crypto_context req_cryptoctx, 5295 pkinit_identity_opts *idopts, 5296 pkinit_identity_crypto_context id_cryptoctx, 5297 int idtype, 5298 int catype, 5299 char *id) 5300 { 5301 pkiDebug("%s: called with idtype %s and catype %s\n", 5302 __FUNCTION__, idtype2string(idtype), catype2string(catype)); 5303 /* Solaris Kerberos: Removed "break"'s as they are never reached */ 5304 switch (idtype) { 5305 case IDTYPE_FILE: 5306 return load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx, 5307 id_cryptoctx, catype, id); 5308 case IDTYPE_DIR: 5309 return load_cas_and_crls_dir(context, plg_cryptoctx, req_cryptoctx, 5310 id_cryptoctx, catype, id); 5311 default: 5312 return ENOTSUP; 5313 } 5314 } 5315 5316 static krb5_error_code 5317 create_identifiers_from_stack(STACK_OF(X509) *sk, 5318 krb5_external_principal_identifier *** ids) 5319 { 5320 krb5_error_code retval = ENOMEM; 5321 int i = 0, sk_size = sk_X509_num(sk); 5322 krb5_external_principal_identifier **krb5_cas = NULL; 5323 X509 *x = NULL; 5324 X509_NAME *xn = NULL; 5325 unsigned char *p = NULL; 5326 int len = 0; 5327 PKCS7_ISSUER_AND_SERIAL *is = NULL; 5328 char buf[DN_BUF_LEN]; 5329 5330 *ids = NULL; 5331 5332 krb5_cas = 5333 malloc((sk_size + 1) * sizeof(krb5_external_principal_identifier *)); 5334 if (krb5_cas == NULL) 5335 return ENOMEM; 5336 krb5_cas[sk_size] = NULL; 5337 5338 for (i = 0; i < sk_size; i++) { 5339 krb5_cas[i] = (krb5_external_principal_identifier *)malloc(sizeof(krb5_external_principal_identifier)); 5340 5341 x = sk_X509_value(sk, i); 5342 5343 X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf)); 5344 pkiDebug("#%d cert= %s\n", i, buf); 5345 5346 /* fill-in subjectName */ 5347 krb5_cas[i]->subjectName.magic = 0; 5348 krb5_cas[i]->subjectName.length = 0; 5349 krb5_cas[i]->subjectName.data = NULL; 5350 5351 xn = X509_get_subject_name(x); 5352 len = i2d_X509_NAME(xn, NULL); 5353 if ((p = krb5_cas[i]->subjectName.data = (unsigned char *)malloc((size_t) len)) == NULL) 5354 goto cleanup; 5355 i2d_X509_NAME(xn, &p); 5356 krb5_cas[i]->subjectName.length = len; 5357 5358 /* fill-in issuerAndSerialNumber */ 5359 krb5_cas[i]->issuerAndSerialNumber.length = 0; 5360 krb5_cas[i]->issuerAndSerialNumber.magic = 0; 5361 krb5_cas[i]->issuerAndSerialNumber.data = NULL; 5362 5363 #ifdef LONGHORN_BETA_COMPAT 5364 if (longhorn == 0) { /* XXX Longhorn doesn't like this */ 5365 #endif 5366 is = PKCS7_ISSUER_AND_SERIAL_new(); 5367 X509_NAME_set(&is->issuer, X509_get_issuer_name(x)); 5368 M_ASN1_INTEGER_free(is->serial); 5369 is->serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(x)); 5370 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL); 5371 if ((p = krb5_cas[i]->issuerAndSerialNumber.data = 5372 (unsigned char *)malloc((size_t) len)) == NULL) 5373 goto cleanup; 5374 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p); 5375 krb5_cas[i]->issuerAndSerialNumber.length = len; 5376 #ifdef LONGHORN_BETA_COMPAT 5377 } 5378 #endif 5379 5380 /* fill-in subjectKeyIdentifier */ 5381 krb5_cas[i]->subjectKeyIdentifier.length = 0; 5382 krb5_cas[i]->subjectKeyIdentifier.magic = 0; 5383 krb5_cas[i]->subjectKeyIdentifier.data = NULL; 5384 5385 5386 #ifdef LONGHORN_BETA_COMPAT 5387 if (longhorn == 0) { /* XXX Longhorn doesn't like this */ 5388 #endif 5389 if (X509_get_ext_by_NID(x, NID_subject_key_identifier, -1) >= 0) { 5390 ASN1_OCTET_STRING *ikeyid = NULL; 5391 5392 if ((ikeyid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, 5393 NULL))) { 5394 len = i2d_ASN1_OCTET_STRING(ikeyid, NULL); 5395 if ((p = krb5_cas[i]->subjectKeyIdentifier.data = 5396 (unsigned char *)malloc((size_t) len)) == NULL) 5397 goto cleanup; 5398 i2d_ASN1_OCTET_STRING(ikeyid, &p); 5399 krb5_cas[i]->subjectKeyIdentifier.length = len; 5400 } 5401 if (ikeyid != NULL) 5402 ASN1_OCTET_STRING_free(ikeyid); 5403 } 5404 #ifdef LONGHORN_BETA_COMPAT 5405 } 5406 #endif 5407 if (is != NULL) { 5408 if (is->issuer != NULL) 5409 X509_NAME_free(is->issuer); 5410 if (is->serial != NULL) 5411 ASN1_INTEGER_free(is->serial); 5412 free(is); 5413 } 5414 } 5415 5416 *ids = krb5_cas; 5417 5418 retval = 0; 5419 cleanup: 5420 if (retval) 5421 free_krb5_external_principal_identifier(&krb5_cas); 5422 5423 return retval; 5424 } 5425 5426 /* ARGSUSED */ 5427 static krb5_error_code 5428 create_krb5_invalidCertificates(krb5_context context, 5429 pkinit_plg_crypto_context plg_cryptoctx, 5430 pkinit_req_crypto_context req_cryptoctx, 5431 pkinit_identity_crypto_context id_cryptoctx, 5432 krb5_external_principal_identifier *** ids) 5433 { 5434 5435 krb5_error_code retval = ENOMEM; 5436 STACK_OF(X509) *sk = NULL; 5437 5438 *ids = NULL; 5439 if (req_cryptoctx->received_cert == NULL) 5440 return KRB5KDC_ERR_PREAUTH_FAILED; 5441 5442 sk = sk_X509_new_null(); 5443 if (sk == NULL) 5444 goto cleanup; 5445 sk_X509_push(sk, req_cryptoctx->received_cert); 5446 5447 retval = create_identifiers_from_stack(sk, ids); 5448 5449 sk_X509_free(sk); 5450 cleanup: 5451 5452 return retval; 5453 } 5454 5455 /* ARGSUSED */ 5456 krb5_error_code 5457 create_krb5_supportedCMSTypes(krb5_context context, 5458 pkinit_plg_crypto_context plg_cryptoctx, 5459 pkinit_req_crypto_context req_cryptoctx, 5460 pkinit_identity_crypto_context id_cryptoctx, 5461 krb5_algorithm_identifier ***oids) 5462 { 5463 5464 krb5_error_code retval = ENOMEM; 5465 krb5_algorithm_identifier **loids = NULL; 5466 krb5_octet_data des3oid = {0, 8, (unsigned char *)"\x2A\x86\x48\x86\xF7\x0D\x03\x07" }; 5467 5468 *oids = NULL; 5469 loids = malloc(2 * sizeof(krb5_algorithm_identifier *)); 5470 if (loids == NULL) 5471 goto cleanup; 5472 loids[1] = NULL; 5473 loids[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier)); 5474 if (loids[0] == NULL) { 5475 free(loids); 5476 goto cleanup; 5477 } 5478 retval = pkinit_copy_krb5_octet_data(&loids[0]->algorithm, &des3oid); 5479 if (retval) { 5480 free(loids[0]); 5481 free(loids); 5482 goto cleanup; 5483 } 5484 loids[0]->parameters.length = 0; 5485 loids[0]->parameters.data = NULL; 5486 5487 *oids = loids; 5488 retval = 0; 5489 cleanup: 5490 5491 return retval; 5492 } 5493 5494 /* ARGSUSED */ 5495 krb5_error_code 5496 create_krb5_trustedCertifiers(krb5_context context, 5497 pkinit_plg_crypto_context plg_cryptoctx, 5498 pkinit_req_crypto_context req_cryptoctx, 5499 pkinit_identity_crypto_context id_cryptoctx, 5500 krb5_external_principal_identifier *** ids) 5501 { 5502 5503 /* Solaris Kerberos */ 5504 STACK_OF(X509) *sk = id_cryptoctx->trustedCAs; 5505 5506 *ids = NULL; 5507 if (id_cryptoctx->trustedCAs == NULL) 5508 return KRB5KDC_ERR_PREAUTH_FAILED; 5509 5510 return create_identifiers_from_stack(sk, ids); 5511 5512 } 5513 5514 /* ARGSUSED */ 5515 krb5_error_code 5516 create_krb5_trustedCas(krb5_context context, 5517 pkinit_plg_crypto_context plg_cryptoctx, 5518 pkinit_req_crypto_context req_cryptoctx, 5519 pkinit_identity_crypto_context id_cryptoctx, 5520 int flag, 5521 krb5_trusted_ca *** ids) 5522 { 5523 krb5_error_code retval = ENOMEM; 5524 STACK_OF(X509) *sk = id_cryptoctx->trustedCAs; 5525 int i = 0, len = 0, sk_size = sk_X509_num(sk); 5526 krb5_trusted_ca **krb5_cas = NULL; 5527 X509 *x = NULL; 5528 char buf[DN_BUF_LEN]; 5529 X509_NAME *xn = NULL; 5530 unsigned char *p = NULL; 5531 PKCS7_ISSUER_AND_SERIAL *is = NULL; 5532 5533 *ids = NULL; 5534 if (id_cryptoctx->trustedCAs == NULL) 5535 return KRB5KDC_ERR_PREAUTH_FAILED; 5536 5537 krb5_cas = malloc((sk_size + 1) * sizeof(krb5_trusted_ca *)); 5538 if (krb5_cas == NULL) 5539 return ENOMEM; 5540 krb5_cas[sk_size] = NULL; 5541 5542 for (i = 0; i < sk_size; i++) { 5543 krb5_cas[i] = (krb5_trusted_ca *)malloc(sizeof(krb5_trusted_ca)); 5544 if (krb5_cas[i] == NULL) 5545 goto cleanup; 5546 x = sk_X509_value(sk, i); 5547 5548 X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf)); 5549 pkiDebug("#%d cert= %s\n", i, buf); 5550 5551 switch (flag) { 5552 case choice_trusted_cas_principalName: 5553 krb5_cas[i]->choice = choice_trusted_cas_principalName; 5554 break; 5555 case choice_trusted_cas_caName: 5556 krb5_cas[i]->choice = choice_trusted_cas_caName; 5557 krb5_cas[i]->u.caName.data = NULL; 5558 krb5_cas[i]->u.caName.length = 0; 5559 xn = X509_get_subject_name(x); 5560 len = i2d_X509_NAME(xn, NULL); 5561 if ((p = krb5_cas[i]->u.caName.data = 5562 (unsigned char *)malloc((size_t) len)) == NULL) 5563 goto cleanup; 5564 i2d_X509_NAME(xn, &p); 5565 krb5_cas[i]->u.caName.length = len; 5566 break; 5567 case choice_trusted_cas_issuerAndSerial: 5568 krb5_cas[i]->choice = choice_trusted_cas_issuerAndSerial; 5569 krb5_cas[i]->u.issuerAndSerial.data = NULL; 5570 krb5_cas[i]->u.issuerAndSerial.length = 0; 5571 is = PKCS7_ISSUER_AND_SERIAL_new(); 5572 X509_NAME_set(&is->issuer, X509_get_issuer_name(x)); 5573 M_ASN1_INTEGER_free(is->serial); 5574 is->serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(x)); 5575 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL); 5576 if ((p = krb5_cas[i]->u.issuerAndSerial.data = 5577 (unsigned char *)malloc((size_t) len)) == NULL) 5578 goto cleanup; 5579 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p); 5580 krb5_cas[i]->u.issuerAndSerial.length = len; 5581 if (is != NULL) { 5582 if (is->issuer != NULL) 5583 X509_NAME_free(is->issuer); 5584 if (is->serial != NULL) 5585 ASN1_INTEGER_free(is->serial); 5586 free(is); 5587 } 5588 break; 5589 default: break; 5590 } 5591 } 5592 retval = 0; 5593 *ids = krb5_cas; 5594 cleanup: 5595 if (retval) 5596 free_krb5_trusted_ca(&krb5_cas); 5597 5598 return retval; 5599 } 5600 5601 /* ARGSUSED */ 5602 krb5_error_code 5603 create_issuerAndSerial(krb5_context context, 5604 pkinit_plg_crypto_context plg_cryptoctx, 5605 pkinit_req_crypto_context req_cryptoctx, 5606 pkinit_identity_crypto_context id_cryptoctx, 5607 unsigned char **out, 5608 unsigned int *out_len) 5609 { 5610 unsigned char *p = NULL; 5611 PKCS7_ISSUER_AND_SERIAL *is = NULL; 5612 int len = 0; 5613 krb5_error_code retval = ENOMEM; 5614 X509 *cert = req_cryptoctx->received_cert; 5615 5616 *out = NULL; 5617 *out_len = 0; 5618 if (req_cryptoctx->received_cert == NULL) 5619 return 0; 5620 5621 is = PKCS7_ISSUER_AND_SERIAL_new(); 5622 X509_NAME_set(&is->issuer, X509_get_issuer_name(cert)); 5623 M_ASN1_INTEGER_free(is->serial); 5624 is->serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(cert)); 5625 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL); 5626 if ((p = *out = (unsigned char *)malloc((size_t) len)) == NULL) 5627 goto cleanup; 5628 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p); 5629 *out_len = len; 5630 retval = 0; 5631 5632 cleanup: 5633 X509_NAME_free(is->issuer); 5634 ASN1_INTEGER_free(is->serial); 5635 free(is); 5636 5637 return retval; 5638 } 5639 5640 static int 5641 pkcs7_decrypt(krb5_context context, 5642 pkinit_identity_crypto_context id_cryptoctx, 5643 PKCS7 *p7, 5644 BIO *data) 5645 { 5646 BIO *tmpmem = NULL; 5647 /* Solaris Kerberos */ 5648 int i = 0; 5649 char buf[4096]; 5650 5651 if(p7 == NULL) 5652 return 0; 5653 5654 if(!PKCS7_type_is_enveloped(p7)) { 5655 pkiDebug("wrong pkcs7 content type\n"); 5656 return 0; 5657 } 5658 5659 if(!(tmpmem = pkcs7_dataDecode(context, id_cryptoctx, p7))) { 5660 pkiDebug("unable to decrypt pkcs7 object\n"); 5661 return 0; 5662 } 5663 /* Solaris Kerberos: Suppress sun studio compiler warning */ 5664 #pragma error_messages (off, E_END_OF_LOOP_CODE_NOT_REACHED) 5665 for(;;) { 5666 i = BIO_read(tmpmem, buf, sizeof(buf)); 5667 if (i <= 0) break; 5668 BIO_write(data, buf, i); 5669 BIO_free_all(tmpmem); 5670 return 1; 5671 } 5672 #pragma error_messages (default, E_END_OF_LOOP_CODE_NOT_REACHED) 5673 5674 return 0; 5675 } 5676 5677 krb5_error_code 5678 pkinit_process_td_trusted_certifiers( 5679 krb5_context context, 5680 pkinit_plg_crypto_context plg_cryptoctx, 5681 pkinit_req_crypto_context req_cryptoctx, 5682 pkinit_identity_crypto_context id_cryptoctx, 5683 krb5_external_principal_identifier **krb5_trusted_certifiers, 5684 int td_type) 5685 { 5686 krb5_error_code retval = ENOMEM; 5687 STACK_OF(X509_NAME) *sk_xn = NULL; 5688 X509_NAME *xn = NULL; 5689 PKCS7_ISSUER_AND_SERIAL *is = NULL; 5690 ASN1_OCTET_STRING *id = NULL; 5691 const unsigned char *p = NULL; 5692 char buf[DN_BUF_LEN]; 5693 int i = 0; 5694 5695 if (td_type == TD_TRUSTED_CERTIFIERS) 5696 pkiDebug("received trusted certifiers\n"); 5697 else 5698 pkiDebug("received invalid certificate\n"); 5699 5700 sk_xn = sk_X509_NAME_new_null(); 5701 while(krb5_trusted_certifiers[i] != NULL) { 5702 if (krb5_trusted_certifiers[i]->subjectName.data != NULL) { 5703 p = krb5_trusted_certifiers[i]->subjectName.data; 5704 xn = d2i_X509_NAME(NULL, &p, 5705 (int)krb5_trusted_certifiers[i]->subjectName.length); 5706 if (xn == NULL) 5707 goto cleanup; 5708 X509_NAME_oneline(xn, buf, sizeof(buf)); 5709 if (td_type == TD_TRUSTED_CERTIFIERS) 5710 pkiDebug("#%d cert = %s is trusted by kdc\n", i, buf); 5711 else 5712 pkiDebug("#%d cert = %s is invalid\n", i, buf); 5713 sk_X509_NAME_push(sk_xn, xn); 5714 } 5715 5716 if (krb5_trusted_certifiers[i]->issuerAndSerialNumber.data != NULL) { 5717 p = krb5_trusted_certifiers[i]->issuerAndSerialNumber.data; 5718 is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p, 5719 (int)krb5_trusted_certifiers[i]->issuerAndSerialNumber.length); 5720 if (is == NULL) 5721 goto cleanup; 5722 X509_NAME_oneline(is->issuer, buf, sizeof(buf)); 5723 if (td_type == TD_TRUSTED_CERTIFIERS) 5724 pkiDebug("#%d issuer = %s serial = %ld is trusted bu kdc\n", i, 5725 buf, ASN1_INTEGER_get(is->serial)); 5726 else 5727 pkiDebug("#%d issuer = %s serial = %ld is invalid\n", i, buf, 5728 ASN1_INTEGER_get(is->serial)); 5729 PKCS7_ISSUER_AND_SERIAL_free(is); 5730 } 5731 5732 if (krb5_trusted_certifiers[i]->subjectKeyIdentifier.data != NULL) { 5733 p = krb5_trusted_certifiers[i]->subjectKeyIdentifier.data; 5734 id = d2i_ASN1_OCTET_STRING(NULL, &p, 5735 (int)krb5_trusted_certifiers[i]->subjectKeyIdentifier.length); 5736 if (id == NULL) 5737 goto cleanup; 5738 /* XXX */ 5739 ASN1_OCTET_STRING_free(id); 5740 } 5741 i++; 5742 } 5743 /* XXX Since we not doing anything with received trusted certifiers 5744 * return an error. this is the place where we can pick a different 5745 * client certificate based on the information in td_trusted_certifiers 5746 */ 5747 retval = KRB5KDC_ERR_PREAUTH_FAILED; 5748 cleanup: 5749 if (sk_xn != NULL) 5750 sk_X509_NAME_pop_free(sk_xn, X509_NAME_free); 5751 5752 return retval; 5753 } 5754 5755 static BIO * 5756 pkcs7_dataDecode(krb5_context context, 5757 pkinit_identity_crypto_context id_cryptoctx, 5758 PKCS7 *p7) 5759 { 5760 int i = 0; 5761 unsigned int jj = 0, tmp_len = 0; 5762 BIO *out=NULL,*etmp=NULL,*bio=NULL; 5763 unsigned char *tmp=NULL; 5764 ASN1_OCTET_STRING *data_body=NULL; 5765 const EVP_CIPHER *evp_cipher=NULL; 5766 EVP_CIPHER_CTX *evp_ctx=NULL; 5767 X509_ALGOR *enc_alg=NULL; 5768 STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; 5769 /* Solaris Kerberos: Not used */ 5770 #if 0 5771 X509_ALGOR *xalg=NULL; 5772 #endif 5773 PKCS7_RECIP_INFO *ri=NULL; 5774 X509 *cert = sk_X509_value(id_cryptoctx->my_certs, 5775 id_cryptoctx->cert_index); 5776 5777 p7->state=PKCS7_S_HEADER; 5778 5779 rsk=p7->d.enveloped->recipientinfo; 5780 enc_alg=p7->d.enveloped->enc_data->algorithm; 5781 data_body=p7->d.enveloped->enc_data->enc_data; 5782 evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm); 5783 if (evp_cipher == NULL) { 5784 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); 5785 goto cleanup; 5786 } 5787 /* Solaris Kerberos: Not used */ 5788 #if 0 5789 xalg=p7->d.enveloped->enc_data->algorithm; 5790 #endif 5791 5792 if ((etmp=BIO_new(BIO_f_cipher())) == NULL) { 5793 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); 5794 goto cleanup; 5795 } 5796 5797 /* It was encrypted, we need to decrypt the secret key 5798 * with the private key */ 5799 5800 /* Find the recipientInfo which matches the passed certificate 5801 * (if any) 5802 */ 5803 5804 if (cert) { 5805 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { 5806 int tmp_ret = 0; 5807 ri=sk_PKCS7_RECIP_INFO_value(rsk,i); 5808 tmp_ret = X509_NAME_cmp(ri->issuer_and_serial->issuer, 5809 cert->cert_info->issuer); 5810 if (!tmp_ret) { 5811 tmp_ret = M_ASN1_INTEGER_cmp(cert->cert_info->serialNumber, 5812 ri->issuer_and_serial->serial); 5813 if (!tmp_ret) 5814 break; 5815 } 5816 ri=NULL; 5817 } 5818 if (ri == NULL) { 5819 PKCS7err(PKCS7_F_PKCS7_DATADECODE, 5820 PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); 5821 goto cleanup; 5822 } 5823 5824 } 5825 5826 /* If we haven't got a certificate try each ri in turn */ 5827 5828 if (cert == NULL) { 5829 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { 5830 ri=sk_PKCS7_RECIP_INFO_value(rsk,i); 5831 jj = pkinit_decode_data(context, id_cryptoctx, 5832 M_ASN1_STRING_data(ri->enc_key), 5833 (unsigned int) M_ASN1_STRING_length(ri->enc_key), 5834 &tmp, &tmp_len); 5835 if (jj) { 5836 PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB); 5837 goto cleanup; 5838 } 5839 5840 if (!jj && tmp_len > 0) { 5841 jj = tmp_len; 5842 break; 5843 } 5844 5845 ERR_clear_error(); 5846 ri = NULL; 5847 } 5848 5849 if (ri == NULL) { 5850 PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_RECIPIENT_MATCHES_KEY); 5851 goto cleanup; 5852 } 5853 } 5854 else { 5855 jj = pkinit_decode_data(context, id_cryptoctx, 5856 M_ASN1_STRING_data(ri->enc_key), 5857 (unsigned int) M_ASN1_STRING_length(ri->enc_key), 5858 &tmp, &tmp_len); 5859 /* Solaris Kerberos: tmp_len is unsigned. Cannot be < 0 */ 5860 if (jj || tmp_len == 0) { 5861 PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB); 5862 goto cleanup; 5863 } 5864 jj = tmp_len; 5865 } 5866 5867 evp_ctx=NULL; 5868 BIO_get_cipher_ctx(etmp,&evp_ctx); 5869 if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0) 5870 goto cleanup; 5871 if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0) 5872 goto cleanup; 5873 5874 if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) { 5875 /* Some S/MIME clients don't use the same key 5876 * and effective key length. The key length is 5877 * determined by the size of the decrypted RSA key. 5878 */ 5879 if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, (int)jj)) { 5880 PKCS7err(PKCS7_F_PKCS7_DATADECODE, 5881 PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH); 5882 goto cleanup; 5883 } 5884 } 5885 if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0) 5886 goto cleanup; 5887 5888 OPENSSL_cleanse(tmp,jj); 5889 5890 if (out == NULL) 5891 out=etmp; 5892 else 5893 BIO_push(out,etmp); 5894 etmp=NULL; 5895 5896 if (data_body->length > 0) 5897 bio = BIO_new_mem_buf(data_body->data, data_body->length); 5898 else { 5899 bio=BIO_new(BIO_s_mem()); 5900 BIO_set_mem_eof_return(bio,0); 5901 } 5902 BIO_push(out,bio); 5903 bio=NULL; 5904 5905 /* Solaris Kerberos */ 5906 goto out; 5907 5908 cleanup: 5909 if (out != NULL) BIO_free_all(out); 5910 if (etmp != NULL) BIO_free_all(etmp); 5911 if (bio != NULL) BIO_free_all(bio); 5912 out=NULL; 5913 5914 out: 5915 if (tmp != NULL) 5916 free(tmp); 5917 5918 return(out); 5919 } 5920 5921 static krb5_error_code 5922 der_decode_data(unsigned char *data, long data_len, 5923 unsigned char **out, long *out_len) 5924 { 5925 /* Solaris Kerberos */ 5926 krb5_error_code retval = KRB5KRB_ERR_GENERIC; 5927 ASN1_OCTET_STRING *s = NULL; 5928 const unsigned char *p = data; 5929 5930 if ((s = d2i_ASN1_BIT_STRING(NULL, &p, data_len)) == NULL) 5931 goto cleanup; 5932 *out_len = s->length; 5933 if ((*out = (unsigned char *) malloc((size_t) *out_len + 1)) == NULL) { 5934 retval = ENOMEM; 5935 goto cleanup; 5936 } 5937 (void) memcpy(*out, s->data, (size_t) s->length); 5938 (*out)[s->length] = '\0'; 5939 5940 retval = 0; 5941 cleanup: 5942 if (s != NULL) 5943 ASN1_OCTET_STRING_free(s); 5944 5945 return retval; 5946 } 5947 5948 5949 #ifdef DEBUG_DH 5950 static void 5951 print_dh(DH * dh, char *msg) 5952 { 5953 BIO *bio_err = NULL; 5954 5955 bio_err = BIO_new(BIO_s_file()); 5956 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); 5957 5958 if (msg) 5959 BIO_puts(bio_err, (const char *)msg); 5960 if (dh) 5961 DHparams_print(bio_err, dh); 5962 5963 BN_print(bio_err, dh->q); 5964 BIO_puts(bio_err, (const char *)"\n"); 5965 BIO_free(bio_err); 5966 5967 } 5968 5969 static void 5970 print_pubkey(BIGNUM * key, char *msg) 5971 { 5972 BIO *bio_err = NULL; 5973 5974 bio_err = BIO_new(BIO_s_file()); 5975 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); 5976 5977 if (msg) 5978 BIO_puts(bio_err, (const char *)msg); 5979 if (key) 5980 BN_print(bio_err, key); 5981 BIO_puts(bio_err, "\n"); 5982 5983 BIO_free(bio_err); 5984 5985 } 5986 #endif 5987 5988 /* 5989 * Solaris Kerberos: 5990 * Error message generation has changed so gettext() can be used 5991 */ 5992 #if 0 5993 static char * 5994 pkinit_pkcs11_code_to_text(int err) 5995 { 5996 int i; 5997 static char uc[64]; 5998 5999 for (i = 0; pkcs11_errstrings[i].text != NULL; i++) 6000 if (pkcs11_errstrings[i].code == err) 6001 break; 6002 if (pkcs11_errstrings[i].text != NULL) 6003 return (pkcs11_errstrings[i].text); 6004 snprintf(uc, 64, gettext("unknown code 0x%x"), err); 6005 return (uc); 6006 } 6007 #endif 6008 6009 static char * 6010 pkinit_pkcs11_code_to_text(int err) { 6011 return pkcs11_error_table(err); 6012 } 6013