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