| 127 | static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond ) |
| 128 | { |
| 129 | struct scd *conn = data; |
| 130 | |
| 131 | return ssl_connected( conn, conn->fd, B_EV_IO_WRITE ); |
| 132 | } |
| 133 | |
| 134 | void *ssl_starttls( int fd, ssl_input_function func, gpointer data ) |
| 135 | { |
| 136 | struct scd *conn = g_new0( struct scd, 1 ); |
| 137 | |
| 138 | conn->fd = fd; |
| 139 | conn->func = func; |
| 140 | conn->data = data; |
| 141 | |
| 142 | /* This function should be called via a (short) timeout instead of |
| 143 | directly from here, because these SSL calls are *supposed* to be |
| 144 | *completely* asynchronous and not ready yet when this function |
| 145 | (or *_connect, for examle) returns. Also, errors are reported via |
| 146 | the callback function, not via this function's return value. |
| 147 | |
| 148 | In short, doing things like this makes the rest of the code a lot |
| 149 | simpler. */ |
| 150 | |
| 151 | b_timeout_add( 1, ssl_starttls_real, conn ); |
| 152 | |
| 153 | return conn; |
| 154 | } |
| 155 | |
| 235 | |
| 236 | size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, |
| 237 | const unsigned char *input, size_t input_len, const unsigned char *iv, |
| 238 | unsigned char **res) |
| 239 | { |
| 240 | int output_length = 0; |
| 241 | |
| 242 | CK_MECHANISM_TYPE cipherMech; |
| 243 | PK11SlotInfo* slot = NULL; |
| 244 | PK11SymKey* SymKey = NULL; |
| 245 | SECItem* SecParam = NULL; |
| 246 | PK11Context* EncContext = NULL; |
| 247 | SECItem keyItem, ivItem; |
| 248 | SECStatus rv1, rv2; |
| 249 | int tmp1_outlen, tmp2_outlen; |
| 250 | |
| 251 | if (!initialized) |
| 252 | { |
| 253 | ssl_init(); |
| 254 | } |
| 255 | |
| 256 | *res = g_new0(unsigned char, 1024); |
| 257 | |
| 258 | cipherMech = CKM_DES3_CBC_PAD; |
| 259 | slot = PK11_GetBestSlot(cipherMech, NULL); |
| 260 | |
| 261 | if (slot == NULL) |
| 262 | { |
| 263 | fprintf(stderr, "Unable to find security device (err %d)\n", |
| 264 | PR_GetError()); |
| 265 | goto out; |
| 266 | } |
| 267 | |
| 268 | // Converts "raw key" into a key object. |
| 269 | keyItem.type = siBuffer; |
| 270 | keyItem.data = (unsigned char*)key; |
| 271 | keyItem.len = key_len; |
| 272 | |
| 273 | SymKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, CKA_ENCRYPT, |
| 274 | &keyItem, NULL); |
| 275 | |
| 276 | if (SymKey == NULL) |
| 277 | { |
| 278 | fprintf(stderr, "Failure to import key into NSS (err %d)\n", |
| 279 | PR_GetError()); |
| 280 | goto out; |
| 281 | } |
| 282 | |
| 283 | /* set up the PKCS11 encryption paramters. |
| 284 | * when not using CBC mode, ivItem.data and ivItem.len can be 0, or you |
| 285 | * can simply pass NULL for the iv parameter in PK11_ParamFromIV func |
| 286 | */ |
| 287 | ivItem.type = siBuffer; |
| 288 | ivItem.data = iv; |
| 289 | ivItem.len = strlen(iv); // ??? Is it right? FIXME |
| 290 | SecParam = PK11_ParamFromIV(cipherMech, &ivItem); |
| 291 | if (SecParam == NULL) |
| 292 | { |
| 293 | fprintf(stderr, "Failure to set up PKCS11 param (err %d)\n", |
| 294 | PR_GetError()); |
| 295 | goto out; |
| 296 | } |
| 297 | |
| 298 | /* ========================= START SECTION ============================= */ |
| 299 | /* If using the the same key and iv over and over, stuff before this */ |
| 300 | /* section and after this section needs to be done only ONCE */ |
| 301 | /* ENCRYPT data into buf1. buf1 len must be atleast (data len + 8) */ |
| 302 | tmp1_outlen = tmp2_outlen = 0; |
| 303 | |
| 304 | /* Create cipher context */ |
| 305 | EncContext = PK11_CreateContextBySymKey(cipherMech, CKA_ENCRYPT, |
| 306 | SymKey, SecParam); |
| 307 | rv1 = PK11_CipherOp(EncContext, res, &tmp1_outlen, sizeof(res), |
| 308 | input, input_len+1); |
| 309 | rv2 = PK11_DigestFinal(EncContext, res+tmp1_outlen, &tmp2_outlen, |
| 310 | sizeof(res)-tmp1_outlen); |
| 311 | PK11_DestroyContext(EncContext, PR_TRUE); |
| 312 | output_length = tmp1_outlen + tmp2_outlen; |
| 313 | if (rv1 != SECSuccess || rv2 != SECSuccess) |
| 314 | goto out; |
| 315 | |
| 316 | return output_length; |
| 317 | |
| 318 | out: |
| 319 | if (SymKey) |
| 320 | PK11_FreeSymKey(SymKey); |
| 321 | if (SecParam) |
| 322 | SECITEM_FreeItem(SecParam, PR_TRUE); |
| 323 | } |