Print this page
9642 PKCS#11 softtoken should use explicit_bzero
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Alex Wilson <alex.wilson@joyent.com>

*** 18,27 **** --- 18,28 ---- * * CDDL HEADER END */ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2018, Joyent, Inc. */ /* * Functions used for manipulating the keystore */
*** 468,479 **** } (void) lock_file(fd, B_FALSE, B_FALSE); (void) close(fd); ! if (hashed_pin_salt) ! free(hashed_pin_salt); return (0); cleanup: (void) lock_file(fd, B_FALSE, B_FALSE); (void) unlink(ks_desc_file); --- 469,479 ---- } (void) lock_file(fd, B_FALSE, B_FALSE); (void) close(fd); ! freezero(hashed_pin_salt, hashed_pin_salt_len); return (0); cleanup: (void) lock_file(fd, B_FALSE, B_FALSE); (void) unlink(ks_desc_file);
*** 890,900 **** return (CKR_HOST_MEMORY); } if ((readn_nointr(fd, *hashed_pin, hashed_pin_size)) != (ssize_t)hashed_pin_size) { ! free(*hashed_pin); *hashed_pin = NULL; return (CKR_FUNCTION_FAILED); } (*hashed_pin)[hashed_pin_size] = '\0'; return (CKR_OK); --- 890,900 ---- return (CKR_HOST_MEMORY); } if ((readn_nointr(fd, *hashed_pin, hashed_pin_size)) != (ssize_t)hashed_pin_size) { ! freezero(*hashed_pin, hashed_pin_size + 1); *hashed_pin = NULL; return (CKR_FUNCTION_FAILED); } (*hashed_pin)[hashed_pin_size] = '\0'; return (CKR_OK);
*** 1318,1397 **** /* decrypt data using old key */ decrypted_len = 0; if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread, NULL, &decrypted_len) != CKR_OK) { ! free(buf); goto cleanup; } decrypted_buf = malloc(decrypted_len); if (decrypted_buf == NULL) { ! free(buf); goto cleanup; } if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread, decrypted_buf, &decrypted_len) != CKR_OK) { ! free(buf); ! free(decrypted_buf); ! goto cleanup; } ! free(buf); /* re-encrypt with new key */ encrypted_len = 0; if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf, decrypted_len, NULL, &encrypted_len) != CKR_OK) { ! free(decrypted_buf); goto cleanup; } buf = malloc(encrypted_len); if (buf == NULL) { ! free(decrypted_buf); goto cleanup; } if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf, decrypted_len, buf, &encrypted_len) != CKR_OK) { ! free(buf); ! free(decrypted_buf); goto cleanup; } ! free(decrypted_buf); /* calculate hmac on re-encrypted data using new hmac key */ hmac_len = OBJ_HMAC_SIZE; if (soft_keystore_hmac(new_hmac_key, B_TRUE, buf, encrypted_len, hmac, &hmac_len) != CKR_OK) { ! free(buf); goto cleanup; } /* just for sanity check */ if (hmac_len != OBJ_HMAC_SIZE) { ! free(buf); goto cleanup; } /* write new hmac */ if (writen_nointr(new_fd, (char *)hmac, OBJ_HMAC_SIZE) != OBJ_HMAC_SIZE) { ! free(buf); goto cleanup; } /* write re-encrypted buffer to temp file */ if (writen_nointr(new_fd, (void *)buf, encrypted_len) != encrypted_len) { ! free(buf); goto cleanup; } ! free(buf); ret_val = 0; cleanup: /* unlock the files */ (void) lock_file(old_fd, B_TRUE, B_FALSE); --- 1318,1396 ---- /* decrypt data using old key */ decrypted_len = 0; if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread, NULL, &decrypted_len) != CKR_OK) { ! freezero(buf, nread); goto cleanup; } decrypted_buf = malloc(decrypted_len); if (decrypted_buf == NULL) { ! freezero(buf, nread); goto cleanup; } if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread, decrypted_buf, &decrypted_len) != CKR_OK) { ! freezero(buf, nread); ! freezero(decrypted_buf, decrypted_len); } ! freezero(buf, nread); /* re-encrypt with new key */ encrypted_len = 0; if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf, decrypted_len, NULL, &encrypted_len) != CKR_OK) { ! freezero(decrypted_buf, decrypted_len); goto cleanup; } buf = malloc(encrypted_len); if (buf == NULL) { ! freezero(decrypted_buf, decrypted_len); goto cleanup; } if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf, decrypted_len, buf, &encrypted_len) != CKR_OK) { ! freezero(buf, encrypted_len); ! freezero(buf, decrypted_len); goto cleanup; } ! freezero(decrypted_buf, decrypted_len); /* calculate hmac on re-encrypted data using new hmac key */ hmac_len = OBJ_HMAC_SIZE; if (soft_keystore_hmac(new_hmac_key, B_TRUE, buf, encrypted_len, hmac, &hmac_len) != CKR_OK) { ! freezero(buf, encrypted_len); goto cleanup; } /* just for sanity check */ if (hmac_len != OBJ_HMAC_SIZE) { ! freezero(buf, encrypted_len); goto cleanup; } /* write new hmac */ if (writen_nointr(new_fd, (char *)hmac, OBJ_HMAC_SIZE) != OBJ_HMAC_SIZE) { ! freezero(buf, encrypted_len); goto cleanup; } /* write re-encrypted buffer to temp file */ if (writen_nointr(new_fd, (void *)buf, encrypted_len) != encrypted_len) { ! freezero(buf, encrypted_len); goto cleanup; } ! freezero(buf, encrypted_len); ret_val = 0; cleanup: /* unlock the files */ (void) lock_file(old_fd, B_TRUE, B_FALSE);
*** 1545,1571 **** != CKR_OK) { goto cleanup; } if (writen_nointr(tmp_ks_fd, (void *)new_crypt_salt, KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) { ! free(new_crypt_salt); (void) soft_cleanup_object(new_crypt_key); goto cleanup; } ! free(new_crypt_salt); if (soft_gen_hmac_key(newpin, &new_hmac_key, &new_hmac_salt) != CKR_OK) { (void) soft_cleanup_object(new_crypt_key); goto cleanup; } if (writen_nointr(tmp_ks_fd, (void *)new_hmac_salt, KS_HMAC_SALT_SIZE) != KS_HMAC_SALT_SIZE) { ! free(new_hmac_salt); goto cleanup3; } ! free(new_hmac_salt); } else { if (soft_gen_crypt_key(newpin, &new_crypt_key, (CK_BYTE **)&crypt_salt) != CKR_OK) { goto cleanup; } --- 1544,1572 ---- != CKR_OK) { goto cleanup; } if (writen_nointr(tmp_ks_fd, (void *)new_crypt_salt, KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) { ! freezero(new_crypt_salt, ! KS_KEY_SALT_SIZE); (void) soft_cleanup_object(new_crypt_key); goto cleanup; } ! freezero(new_crypt_salt, KS_KEY_SALT_SIZE); if (soft_gen_hmac_key(newpin, &new_hmac_key, &new_hmac_salt) != CKR_OK) { (void) soft_cleanup_object(new_crypt_key); goto cleanup; } if (writen_nointr(tmp_ks_fd, (void *)new_hmac_salt, KS_HMAC_SALT_SIZE) != KS_HMAC_SALT_SIZE) { ! freezero(new_hmac_salt, ! KS_HMAC_SALT_SIZE); goto cleanup3; } ! freezero(new_hmac_salt, KS_HMAC_SALT_SIZE); } else { if (soft_gen_crypt_key(newpin, &new_crypt_key, (CK_BYTE **)&crypt_salt) != CKR_OK) { goto cleanup; }
*** 1610,1639 **** goto cleanup3; } if ((readn_nointr(fd, hashed_pin_salt, hashed_pin_salt_length)) != (ssize_t)hashed_pin_salt_length) { ! free(hashed_pin_salt); goto cleanup3; } if ((writen_nointr(tmp_ks_fd, hashed_pin_salt, hashed_pin_salt_length)) != (ssize_t)hashed_pin_salt_length) { ! free(hashed_pin_salt); goto cleanup3; } hashed_pin_salt[hashed_pin_salt_length] = '\0'; /* old hashed pin length and value can be ignored, generate new one */ if (soft_gen_hashed_pin(newpin, &new_hashed_pin, &hashed_pin_salt) < 0) { ! free(hashed_pin_salt); goto cleanup3; } ! free(hashed_pin_salt); if (new_hashed_pin == NULL) { goto cleanup3; } --- 1611,1643 ---- goto cleanup3; } if ((readn_nointr(fd, hashed_pin_salt, hashed_pin_salt_length)) != (ssize_t)hashed_pin_salt_length) { ! freezero(hashed_pin_salt, ! hashed_pin_salt_length + 1); goto cleanup3; } if ((writen_nointr(tmp_ks_fd, hashed_pin_salt, hashed_pin_salt_length)) != (ssize_t)hashed_pin_salt_length) { ! freezero(hashed_pin_salt, ! hashed_pin_salt_length + 1); goto cleanup3; } hashed_pin_salt[hashed_pin_salt_length] = '\0'; /* old hashed pin length and value can be ignored, generate new one */ if (soft_gen_hashed_pin(newpin, &new_hashed_pin, &hashed_pin_salt) < 0) { ! freezero(hashed_pin_salt, ! hashed_pin_salt_length + 1); goto cleanup3; } ! freezero(hashed_pin_salt, hashed_pin_salt_length + 1); if (new_hashed_pin == NULL) { goto cleanup3; }
*** 1761,1776 **** if (!lock_held) { if (lock_file(fd, B_FALSE, B_FALSE) < 0) { ret_val = 1; } } ! if (crypt_salt != NULL) { ! free(crypt_salt); ! } ! if (hmac_salt != NULL) { ! free(hmac_salt); ! } (void) close(fd); (void) close(tmp_ks_fd); if (ret_val != 0) { (void) remove(tmp_ks_desc_name); } --- 1765,1776 ---- if (!lock_held) { if (lock_file(fd, B_FALSE, B_FALSE) < 0) { ret_val = 1; } } ! freezero(crypt_salt, KS_KEY_SALT_SIZE); ! freezero(hmac_salt, KS_HMAC_SALT_SIZE); (void) close(fd); (void) close(tmp_ks_fd); if (ret_val != 0) { (void) remove(tmp_ks_desc_name); }
*** 1853,1868 **** cleanup: /* unlock the file */ (void) lock_file(fd, B_TRUE, B_FALSE); (void) close(fd); ! if (crypt_salt != NULL) { ! free(crypt_salt); ! } ! if (hmac_salt != NULL) { ! free(hmac_salt); ! } return (ret_val); } /* * FUNCTION: soft_keystore_get_objs --- 1853,1864 ---- cleanup: /* unlock the file */ (void) lock_file(fd, B_TRUE, B_FALSE); (void) close(fd); ! freezero(crypt_salt, KS_KEY_SALT_SIZE); ! freezero(hmac_salt, KS_HMAC_SALT_SIZE); return (ret_val); } /* * FUNCTION: soft_keystore_get_objs
*** 1978,1988 **** /* free all the objects found before hitting the error */ tmp = *result_obj_list; while (tmp) { *result_obj_list = tmp->next; ! free(tmp->buf); free(tmp); tmp = *result_obj_list; } *result_obj_list = NULL; return (rv); --- 1974,1984 ---- /* free all the objects found before hitting the error */ tmp = *result_obj_list; while (tmp) { *result_obj_list = tmp->next; ! freezero(tmp->buf, tmp->size); free(tmp); tmp = *result_obj_list; } *result_obj_list = NULL; return (rv);
*** 2085,2118 **** /* verify HMAC of the object, make sure it matches */ hmac_size = OBJ_HMAC_SIZE; if (soft_keystore_hmac(hmac_key, B_FALSE, buf, nread, obj_hmac, &hmac_size) != CKR_OK) { ! free(buf); rv = CKR_FUNCTION_FAILED; goto cleanup; } /* decrypt object */ if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread, NULL, &out_len) != CKR_OK) { ! free(buf); rv = CKR_FUNCTION_FAILED; goto cleanup; } decrypted_buf = malloc(sizeof (uchar_t) * out_len); if (decrypted_buf == NULL) { ! free(buf); rv = CKR_HOST_MEMORY; goto cleanup; } if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread, decrypted_buf, &out_len) != CKR_OK) { ! free(decrypted_buf); ! free(buf); rv = CKR_FUNCTION_FAILED; goto cleanup; } obj->size = out_len - MAXPATHLEN; --- 2081,2114 ---- /* verify HMAC of the object, make sure it matches */ hmac_size = OBJ_HMAC_SIZE; if (soft_keystore_hmac(hmac_key, B_FALSE, buf, nread, obj_hmac, &hmac_size) != CKR_OK) { ! freezero(buf, nread); rv = CKR_FUNCTION_FAILED; goto cleanup; } /* decrypt object */ if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread, NULL, &out_len) != CKR_OK) { ! freezero(buf, nread); rv = CKR_FUNCTION_FAILED; goto cleanup; } decrypted_buf = malloc(sizeof (uchar_t) * out_len); if (decrypted_buf == NULL) { ! freezero(buf, nread); rv = CKR_HOST_MEMORY; goto cleanup; } if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread, decrypted_buf, &out_len) != CKR_OK) { ! freezero(buf, nread); ! freezero(decrypted_buf, out_len); rv = CKR_FUNCTION_FAILED; goto cleanup; } obj->size = out_len - MAXPATHLEN;
*** 2124,2141 **** * See prepare_data_for_encrypt() function in the file * to understand how and why the pathname is added. */ obj->buf = malloc(sizeof (uchar_t) * (out_len - MAXPATHLEN)); if (obj->buf == NULL) { ! free(decrypted_buf); ! free(buf); rv = CKR_HOST_MEMORY; goto cleanup; } (void) memcpy(obj->buf, decrypted_buf + MAXPATHLEN, obj->size); ! free(decrypted_buf); ! free(buf); *return_obj = obj; } cleanup: --- 2120,2137 ---- * See prepare_data_for_encrypt() function in the file * to understand how and why the pathname is added. */ obj->buf = malloc(sizeof (uchar_t) * (out_len - MAXPATHLEN)); if (obj->buf == NULL) { ! freezero(buf, nread); ! freezero(decrypted_buf, out_len); rv = CKR_HOST_MEMORY; goto cleanup; } (void) memcpy(obj->buf, decrypted_buf + MAXPATHLEN, obj->size); ! freezero(buf, nread); ! freezero(decrypted_buf, out_len); *return_obj = obj; } cleanup:
*** 2334,2390 **** } if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf, prepared_len, NULL, &out_len) != CKR_OK) { ! free(prepared_buf); goto cleanup2; } encrypted_buf = malloc(out_len * sizeof (char)); if (encrypted_buf == NULL) { ! free(prepared_buf); goto cleanup2; } if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf, prepared_len, encrypted_buf, &out_len) != CKR_OK) { ! free(encrypted_buf); ! free(prepared_buf); goto cleanup2; } ! free(prepared_buf); /* calculate HMAC of encrypted object */ hmac_size = OBJ_HMAC_SIZE; if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf, out_len, obj_hmac, &hmac_size) != CKR_OK) { ! free(encrypted_buf); goto cleanup2; } if (hmac_size != OBJ_HMAC_SIZE) { ! free(encrypted_buf); goto cleanup2; } /* write hmac */ if (writen_nointr(obj_fd, (void *)obj_hmac, sizeof (obj_hmac)) != sizeof (obj_hmac)) { ! free(encrypted_buf); goto cleanup2; } /* write encrypted object */ if (writen_nointr(obj_fd, (void *)encrypted_buf, out_len) != out_len) { ! free(encrypted_buf); goto cleanup2; } ! free(encrypted_buf); } (void) close(obj_fd); (void) snprintf((char *)keyhandle->name, sizeof (keyhandle->name), --- 2330,2386 ---- } if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf, prepared_len, NULL, &out_len) != CKR_OK) { ! freezero(prepared_buf, prepared_len); goto cleanup2; } encrypted_buf = malloc(out_len * sizeof (char)); if (encrypted_buf == NULL) { ! freezero(prepared_buf, prepared_len); goto cleanup2; } if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf, prepared_len, encrypted_buf, &out_len) != CKR_OK) { ! freezero(encrypted_buf, out_len); ! freezero(prepared_buf, prepared_len); goto cleanup2; } ! freezero(prepared_buf, prepared_len); /* calculate HMAC of encrypted object */ hmac_size = OBJ_HMAC_SIZE; if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf, out_len, obj_hmac, &hmac_size) != CKR_OK) { ! freezero(encrypted_buf, out_len); goto cleanup2; } if (hmac_size != OBJ_HMAC_SIZE) { ! freezero(encrypted_buf, out_len); goto cleanup2; } /* write hmac */ if (writen_nointr(obj_fd, (void *)obj_hmac, sizeof (obj_hmac)) != sizeof (obj_hmac)) { ! freezero(encrypted_buf, out_len); goto cleanup2; } /* write encrypted object */ if (writen_nointr(obj_fd, (void *)encrypted_buf, out_len) != out_len) { ! freezero(encrypted_buf, out_len); goto cleanup2; } ! freezero(encrypted_buf, out_len); } (void) close(obj_fd); (void) snprintf((char *)keyhandle->name, sizeof (keyhandle->name),
*** 2419,2428 **** --- 2415,2426 ---- (void) close(fd); return (-1); } } (void) close(fd); + explicit_bzero(obj_hmac, sizeof (obj_hmac)); + explicit_bzero(iv, sizeof (iv)); return (0); cleanup2: /* remove object file. No need to remove lock first */
*** 2436,2445 **** --- 2434,2445 ---- /* release lock on description file */ (void) lock_file(fd, B_FALSE, B_FALSE); } (void) close(fd); + explicit_bzero(obj_hmac, sizeof (obj_hmac)); + explicit_bzero(iv, sizeof (iv)); return (-1); } /* * FUNCTION: soft_keystore_modify_obj
*** 2589,2636 **** goto cleanup2; } encrypted_buf = malloc(out_len * sizeof (char)); if (encrypted_buf == NULL) { ! free(prepared_buf); goto cleanup2; } if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf, prepared_len, encrypted_buf, &out_len) != CKR_OK) { ! free(encrypted_buf); ! free(prepared_buf); goto cleanup2; } ! free(prepared_buf); /* calculate hmac on encrypted buf */ hmac_size = OBJ_HMAC_SIZE; if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf, out_len, obj_hmac, &hmac_size) != CKR_OK) { ! free(encrypted_buf); goto cleanup2; } if (hmac_size != OBJ_HMAC_SIZE) { ! free(encrypted_buf); goto cleanup2; } if (writen_nointr(tmp_fd, (char *)obj_hmac, OBJ_HMAC_SIZE) != OBJ_HMAC_SIZE) { ! free(encrypted_buf); goto cleanup2; } if (writen_nointr(tmp_fd, (void *)encrypted_buf, out_len) != out_len) { ! free(encrypted_buf); goto cleanup2; } ! free(encrypted_buf); } (void) close(tmp_fd); /* rename updated temporary object file */ if (rename(tmp_name, orig_name) != 0) { --- 2589,2636 ---- goto cleanup2; } encrypted_buf = malloc(out_len * sizeof (char)); if (encrypted_buf == NULL) { ! freezero(prepared_buf, prepared_len); goto cleanup2; } if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf, prepared_len, encrypted_buf, &out_len) != CKR_OK) { ! freezero(prepared_buf, prepared_len); ! freezero(encrypted_buf, out_len); goto cleanup2; } ! freezero(prepared_buf, prepared_len); /* calculate hmac on encrypted buf */ hmac_size = OBJ_HMAC_SIZE; if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf, out_len, obj_hmac, &hmac_size) != CKR_OK) { ! freezero(encrypted_buf, out_len); goto cleanup2; } if (hmac_size != OBJ_HMAC_SIZE) { ! freezero(encrypted_buf, out_len); goto cleanup2; } if (writen_nointr(tmp_fd, (char *)obj_hmac, OBJ_HMAC_SIZE) != OBJ_HMAC_SIZE) { ! freezero(encrypted_buf, out_len); goto cleanup2; } if (writen_nointr(tmp_fd, (void *)encrypted_buf, out_len) != out_len) { ! freezero(encrypted_buf, out_len); goto cleanup2; } ! freezero(encrypted_buf, out_len); } (void) close(tmp_fd); /* rename updated temporary object file */ if (rename(tmp_name, orig_name) != 0) {
*** 2663,2672 **** --- 2663,2674 ---- (void) close(ks_fd); (void) close(fd); + explicit_bzero(iv, sizeof (iv)); + explicit_bzero(obj_hmac, sizeof (obj_hmac)); return (0); /* All operations completed successfully */ cleanup2: (void) close(tmp_fd); (void) remove(tmp_name);
*** 2677,2686 **** --- 2679,2690 ---- cleanup: /* unlock keystore description file */ (void) lock_file(ks_fd, B_FALSE, B_FALSE); (void) close(ks_fd); (void) remove(tmp_ks_name); + explicit_bzero(iv, sizeof (iv)); + explicit_bzero(obj_hmac, sizeof (obj_hmac)); return (-1); } /* * FUNCTION: soft_keystore_del_obj
*** 2801,2811 **** goto cleanup; } if ((readn_nointr(fd, *salt, hashed_pin_salt_size)) != (ssize_t)hashed_pin_salt_size) { ! free(*salt); goto cleanup; } (*salt)[hashed_pin_salt_size] = '\0'; ret_val = 0; --- 2805,2815 ---- goto cleanup; } if ((readn_nointr(fd, *salt, hashed_pin_salt_size)) != (ssize_t)hashed_pin_salt_size) { ! freezero(*salt, hashed_pin_salt_size + 1); goto cleanup; } (*salt)[hashed_pin_salt_size] = '\0'; ret_val = 0;