| /* |
| Common Public License Version 0.5 |
| |
| THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF |
| THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, |
| REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES |
| RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. |
| |
| 1. DEFINITIONS |
| |
| "Contribution" means: |
| a) in the case of the initial Contributor, the |
| initial code and documentation distributed under |
| this Agreement, and |
| |
| b) in the case of each subsequent Contributor: |
| i) changes to the Program, and |
| ii) additions to the Program; |
| |
| where such changes and/or additions to the Program |
| originate from and are distributed by that |
| particular Contributor. A Contribution 'originates' |
| from a Contributor if it was added to the Program |
| by such Contributor itself or anyone acting on such |
| Contributor's behalf. Contributions do not include |
| additions to the Program which: (i) are separate |
| modules of software distributed in conjunction with |
| the Program under their own license agreement, and |
| (ii) are not derivative works of the Program. |
| |
| |
| "Contributor" means any person or entity that distributes |
| the Program. |
| |
| "Licensed Patents " mean patent claims licensable by a |
| Contributor which are necessarily infringed by the use or |
| sale of its Contribution alone or when combined with the |
| Program. |
| |
| "Program" means the Contributions distributed in |
| accordance with this Agreement. |
| |
| "Recipient" means anyone who receives the Program under |
| this Agreement, including all Contributors. |
| |
| 2. GRANT OF RIGHTS |
| |
| a) Subject to the terms of this Agreement, each |
| Contributor hereby grants Recipient a |
| non-exclusive, worldwide, royalty-free copyright |
| license to reproduce, prepare derivative works of, |
| publicly display, publicly perform, distribute and |
| sublicense the Contribution of such Contributor, if |
| any, and such derivative works, in source code and |
| object code form. |
| |
| b) Subject to the terms of this Agreement, each |
| Contributor hereby grants Recipient a |
| non-exclusive, worldwide, royalty-free patent |
| license under Licensed Patents to make, use, sell, |
| offer to sell, import and otherwise transfer the |
| Contribution of such Contributor, if any, in source |
| code and object code form. This patent license |
| shall apply to the combination of the Contribution |
| and the Program if, at the time the Contribution is |
| added by the Contributor, such addition of the |
| Contribution causes such combination to be covered |
| by the Licensed Patents. The patent license shall |
| not apply to any other combinations which include |
| the Contribution. No hardware per se is licensed |
| hereunder. |
| |
| c) Recipient understands that although each |
| Contributor grants the licenses to its |
| Contributions set forth herein, no assurances are |
| provided by any Contributor that the Program does |
| not infringe the patent or other intellectual |
| property rights of any other entity. Each |
| Contributor disclaims any liability to Recipient |
| for claims brought by any other entity based on |
| infringement of intellectual property rights or |
| otherwise. As a condition to exercising the rights |
| and licenses granted hereunder, each Recipient |
| hereby assumes sole responsibility to secure any |
| other intellectual property rights needed, if any. |
| |
| For example, if a third party patent license is |
| required to allow Recipient to distribute the |
| Program, it is Recipient's responsibility to |
| acquire that license before distributing the |
| Program. |
| |
| d) Each Contributor represents that to its |
| knowledge it has sufficient copyright rights in its |
| Contribution, if any, to grant the copyright |
| license set forth in this Agreement. |
| |
| 3. REQUIREMENTS |
| |
| A Contributor may choose to distribute the Program in |
| object code form under its own license agreement, provided |
| that: |
| a) it complies with the terms and conditions of |
| this Agreement; and |
| |
| b) its license agreement: |
| i) effectively disclaims on behalf of all |
| Contributors all warranties and conditions, express |
| and implied, including warranties or conditions of |
| title and non-infringement, and implied warranties |
| or conditions of merchantability and fitness for a |
| particular purpose; |
| |
| ii) effectively excludes on behalf of all |
| Contributors all liability for damages, including |
| direct, indirect, special, incidental and |
| consequential damages, such as lost profits; |
| |
| iii) states that any provisions which differ from |
| this Agreement are offered by that Contributor |
| alone and not by any other party; and |
| |
| iv) states that source code for the Program is |
| available from such Contributor, and informs |
| licensees how to obtain it in a reasonable manner |
| on or through a medium customarily used for |
| software exchange. |
| |
| When the Program is made available in source code form: |
| a) it must be made available under this Agreement; |
| and |
| b) a copy of this Agreement must be included with |
| each copy of the Program. |
| |
| Contributors may not remove or alter any copyright notices |
| contained within the Program. |
| |
| Each Contributor must identify itself as the originator of |
| its Contribution, if any, in a manner that reasonably |
| allows subsequent Recipients to identify the originator of |
| the Contribution. |
| |
| |
| 4. COMMERCIAL DISTRIBUTION |
| |
| Commercial distributors of software may accept certain |
| responsibilities with respect to end users, business |
| partners and the like. While this license is intended to |
| facilitate the commercial use of the Program, the |
| Contributor who includes the Program in a commercial |
| product offering should do so in a manner which does not |
| create potential liability for other Contributors. |
| Therefore, if a Contributor includes the Program in a |
| commercial product offering, such Contributor ("Commercial |
| Contributor") hereby agrees to defend and indemnify every |
| other Contributor ("Indemnified Contributor") against any |
| losses, damages and costs (collectively "Losses") arising |
| from claims, lawsuits and other legal actions brought by a |
| third party against the Indemnified Contributor to the |
| extent caused by the acts or omissions of such Commercial |
| Contributor in connection with its distribution of the |
| Program in a commercial product offering. The obligations |
| in this section do not apply to any claims or Losses |
| relating to any actual or alleged intellectual property |
| infringement. In order to qualify, an Indemnified |
| Contributor must: a) promptly notify the Commercial |
| Contributor in writing of such claim, and b) allow the |
| Commercial Contributor to control, and cooperate with the |
| Commercial Contributor in, the defense and any related |
| settlement negotiations. The Indemnified Contributor may |
| participate in any such claim at its own expense. |
| |
| |
| For example, a Contributor might include the Program in a |
| commercial product offering, Product X. That Contributor |
| is then a Commercial Contributor. If that Commercial |
| Contributor then makes performance claims, or offers |
| warranties related to Product X, those performance claims |
| and warranties are such Commercial Contributor's |
| responsibility alone. Under this section, the Commercial |
| Contributor would have to defend claims against the other |
| Contributors related to those performance claims and |
| warranties, and if a court requires any other Contributor |
| to pay any damages as a result, the Commercial Contributor |
| must pay those damages. |
| |
| |
| 5. NO WARRANTY |
| |
| EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE |
| PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT |
| WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR |
| IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR |
| CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR |
| FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely |
| responsible for determining the appropriateness of using |
| and distributing the Program and assumes all risks |
| associated with its exercise of rights under this |
| Agreement, including but not limited to the risks and |
| costs of program errors, compliance with applicable laws, |
| damage to or loss of data, programs or equipment, and |
| unavailability or interruption of operations. |
| |
| 6. DISCLAIMER OF LIABILITY |
| EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER |
| RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY |
| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, |
| OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION |
| LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF |
| LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE |
| OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE |
| POSSIBILITY OF SUCH DAMAGES. |
| |
| 7. GENERAL |
| |
| If any provision of this Agreement is invalid or |
| unenforceable under applicable law, it shall not affect |
| the validity or enforceability of the remainder of the |
| terms of this Agreement, and without further action by the |
| parties hereto, such provision shall be reformed to the |
| minimum extent necessary to make such provision valid and |
| enforceable. |
| |
| |
| If Recipient institutes patent litigation against a |
| Contributor with respect to a patent applicable to |
| software (including a cross-claim or counterclaim in a |
| lawsuit), then any patent licenses granted by that |
| Contributor to such Recipient under this Agreement shall |
| terminate as of the date such litigation is filed. In |
| addition, If Recipient institutes patent litigation |
| against any entity (including a cross-claim or |
| counterclaim in a lawsuit) alleging that the Program |
| itself (excluding combinations of the Program with other |
| software or hardware) infringes such Recipient's |
| patent(s), then such Recipient's rights granted under |
| Section 2(b) shall terminate as of the date such |
| litigation is filed. |
| |
| All Recipient's rights under this Agreement shall |
| terminate if it fails to comply with any of the material |
| terms or conditions of this Agreement and does not cure |
| such failure in a reasonable period of time after becoming |
| aware of such noncompliance. If all Recipient's rights |
| under this Agreement terminate, Recipient agrees to cease |
| use and distribution of the Program as soon as reasonably |
| practicable. However, Recipient's obligations under this |
| Agreement and any licenses granted by Recipient relating |
| to the Program shall continue and survive. |
| |
| Everyone is permitted to copy and distribute copies of |
| this Agreement, but in order to avoid inconsistency the |
| Agreement is copyrighted and may only be modified in the |
| following manner. The Agreement Steward reserves the right |
| to publish new versions (including revisions) of this |
| Agreement from time to time. No one other than the |
| Agreement Steward has the right to modify this Agreement. |
| |
| IBM is the initial Agreement Steward. IBM may assign the |
| responsibility to serve as the Agreement Steward to a |
| suitable separate entity. Each new version of the |
| Agreement will be given a distinguishing version number. |
| The Program (including Contributions) may always be |
| distributed subject to the version of the Agreement under |
| which it was received. In addition, after a new version of |
| the Agreement is published, Contributor may elect to |
| distribute the Program (including its Contributions) under |
| the new version. Except as expressly stated in Sections |
| 2(a) and 2(b) above, Recipient receives no rights or |
| licenses to the intellectual property of any Contributor |
| under this Agreement, whether expressly, by implication, |
| estoppel or otherwise. All rights in the Program not |
| expressly granted under this Agreement are reserved. |
| |
| |
| This Agreement is governed by the laws of the State of New |
| York and the intellectual property laws of the United |
| States of America. No party to this Agreement will bring a |
| legal action under this Agreement more than one year after |
| the cause of action arose. Each party waives its rights to |
| a jury trial in any resulting litigation. |
| |
| |
| |
| */ |
| |
| /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ |
| |
| |
| // loadsave.c |
| // |
| // routines associated with loading/saving files |
| // |
| // |
| |
| #include <pthread.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <sys/ipc.h> |
| #include <sys/file.h> |
| #include <errno.h> |
| |
| #include <pwd.h> |
| #include <grp.h> |
| |
| #include <pkcs11/pkcs11types.h> |
| #include <pkcs11/stdll.h> |
| #include "defs.h" |
| #include "host_defs.h" |
| #include "h_extern.h" |
| #include "tok_spec_struct.h" |
| #include "pkcs32.h" |
| //#include "args.h" |
| |
| #include "../api/apiproto.h" |
| |
| #define MK_SIZE (AES_KEY_SIZE_256) |
| |
| extern CK_BYTE master_key_private[MK_SIZE]; |
| |
| void |
| set_perm(int file) |
| { |
| struct group *grp; |
| |
| // Set absolute permissions of rw-rw---- |
| fchmod(file,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); |
| |
| grp = getgrnam("pkcs11"); // Obtain the group id |
| if (grp){ |
| fchown(file,getuid(),grp->gr_gid); // set ownership to root, and pkcs11 group |
| } |
| } |
| |
| // |
| // |
| CK_RV |
| load_token_data() |
| { |
| FILE * fp; |
| CK_BYTE fname[PATH_MAX]; |
| TOKEN_DATA td; |
| CK_BYTE clear[3 * DES_BLOCK_SIZE]; // enough to hold a CBC-encrypted SHA hash |
| CK_BYTE cipher[3 * DES_BLOCK_SIZE]; |
| CK_ULONG clear_len, cipher_len; |
| CK_RV rc; |
| struct passwd *pw = NULL; |
| |
| if ((pw = getpwuid(getuid())) == NULL){ |
| LogError("getpwuid failed: %s", strerror(errno)); |
| return CKR_FUNCTION_FAILED; |
| } |
| |
| sprintf((char *)fname,"%s/%s/%s",(char *)pk_dir, pw->pw_name, PK_LITE_NV); |
| |
| rc = XProcLock( xproclock ); |
| if (rc != CKR_OK){ |
| st_err_log(150, __FILE__, __LINE__); |
| goto out_nolock; |
| } |
| |
| //sprintf((char *)fname,"%s/%s",(char *)pk_dir, PK_LITE_NV); |
| |
| //fp = fopen("/tmp/NVTOK.DAT", "r"); |
| fp = fopen((char *)fname, "r"); |
| if (!fp) { |
| /* Better error checking added */ |
| if (errno == ENOENT) { |
| /* init_token_data may call save_token_data, which graps the |
| * xproclock, so we must release it around this call */ |
| XProcUnLock( xproclock ); |
| init_token_data(); |
| rc = XProcLock( xproclock ); |
| if (rc != CKR_OK){ |
| st_err_log(150, __FILE__, __LINE__); |
| goto out_nolock; |
| } |
| |
| //fp = fopen("/tmp/NVTOK.DAT", "r"); |
| fp = fopen((char *)fname, "r"); |
| if (!fp) { |
| // were really hosed here since the created |
| // did not occur |
| //st_err_log(194, __FILE__, __LINE__, PK_LITE_NV, errno); |
| LogError("failed opening %s for read: %s", fname, strerror(errno)); |
| rc = CKR_FUNCTION_FAILED; |
| goto out_unlock; |
| } |
| } else { |
| /* Could not open file for some unknown reason */ |
| st_err_log(194, __FILE__, __LINE__, PK_LITE_NV, errno); |
| rc = CKR_FUNCTION_FAILED; |
| goto out_unlock; |
| } |
| } |
| set_perm(fileno(fp)); |
| |
| rc = fread( &td, sizeof(TOKEN_DATA), 1, fp ); |
| fclose(fp); |
| |
| if (rc == 0) { |
| rc = CKR_FUNCTION_FAILED; |
| goto out_unlock; |
| } |
| |
| // memcpy( cipher, &td.user_pin_sha, 3*DES_BLOCK_SIZE ); |
| // clear_len = cipher_len = 3 * DES_BLOCK_SIZE; |
| // rc = ckm_des3_cbc_decrypt( cipher, cipher_len, clear, &clear_len, "12345678", master_key ); |
| // if (rc != CKR_OK) |
| // return CKR_FUNCTION_FAILED; |
| // |
| // memcpy( &td.user_pin_sha, clear, clear_len ); |
| // |
| // memcpy( cipher, &td.so_pin_sha, 3*DES_BLOCK_SIZE ); |
| // clear_len = cipher_len = 3 * DES_BLOCK_SIZE; |
| // rc = ckm_des3_cbc_decrypt( cipher, cipher_len, clear, &clear_len, "12345678", master_key ); |
| // if (rc != CKR_OK) |
| // return CKR_FUNCTION_FAILED; |
| // |
| // memcpy( &td.so_pin_sha, clear, clear_len ); |
| |
| memcpy( nv_token_data, &td, sizeof(TOKEN_DATA) ); |
| |
| rc = CKR_OK; |
| |
| out_unlock: |
| XProcUnLock( xproclock ); |
| |
| out_nolock: |
| return rc; |
| } |
| |
| |
| // |
| // |
| CK_RV |
| save_token_data() |
| { |
| FILE *fp; |
| TOKEN_DATA td; |
| CK_BYTE clear[3 * DES_BLOCK_SIZE]; |
| CK_BYTE cipher[3 * DES_BLOCK_SIZE]; |
| CK_ULONG clear_len, cipher_len; |
| CK_RV rc; |
| CK_BYTE fname[PATH_MAX]; |
| struct passwd *pw = NULL; |
| |
| if ((pw = getpwuid(getuid())) == NULL){ |
| LogError("getpwuid failed: %s", strerror(errno)); |
| return CKR_FUNCTION_FAILED; |
| } |
| |
| sprintf((char *)fname,"%s/%s/%s",(char *)pk_dir, pw->pw_name, PK_LITE_NV); |
| |
| rc = XProcLock( xproclock ); |
| if (rc != CKR_OK){ |
| st_err_log(150, __FILE__, __LINE__); |
| goto out_nolock; |
| } |
| |
| //sprintf((char *)fname,"%s/%s",pk_dir, PK_LITE_NV); |
| //fp = fopen("/tmp/NVTOK.DAT", "w"); |
| fp = fopen((char *)fname, "r+"); |
| if (!fp){ |
| fp = fopen((char *)fname, "w"); |
| if (!fp) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto done; |
| } |
| } |
| set_perm(fileno(fp)); |
| |
| memcpy( &td, nv_token_data, sizeof(TOKEN_DATA) ); |
| |
| // memcpy( clear, nv_token_data->user_pin_sha, SHA1_HASH_SIZE ); |
| // memcpy( clear + SHA1_HASH_SIZE, "1234", 4 ); |
| // clear_len = cipher_len = 3 * DES_KEY_SIZE; |
| // rc = ckm_des3_cbc_encrypt( clear, clear_len, cipher, &cipher_len, "12345678", master_key ); |
| // if (rc != CKR_OK) |
| // goto done; |
| // |
| // memcpy( td.user_pin_sha, cipher, 3*DES_BLOCK_SIZE ); |
| // |
| // memcpy( clear, nv_token_data->so_pin_sha, SHA1_HASH_SIZE ); |
| // memcpy( clear + SHA1_HASH_SIZE, "1234", 4 ); |
| // clear_len = cipher_len = 3 * DES_KEY_SIZE; |
| // rc = ckm_des3_cbc_encrypt( clear, clear_len, cipher, &cipher_len, "12345678", master_key ); |
| // if (rc != CKR_OK) |
| // goto done; |
| // |
| // memcpy( td.so_pin_sha, cipher, 3*DES_BLOCK_SIZE ); |
| |
| (void)fwrite( &td, sizeof(TOKEN_DATA), 1, fp ); |
| fclose(fp); |
| |
| rc = CKR_OK; |
| |
| done: |
| XProcUnLock( xproclock ); |
| |
| out_nolock: |
| return rc; |
| } |
| |
| |
| // |
| // |
| CK_RV |
| save_token_object( OBJECT *obj ) |
| { |
| FILE * fp = NULL; |
| CK_BYTE line[100]; |
| CK_RV rc; |
| CK_BYTE fname[PATH_MAX]; |
| struct passwd *pw = NULL; |
| |
| |
| if (object_is_private(obj) == TRUE) |
| rc = save_private_token_object( obj ); |
| else |
| rc = save_public_token_object( obj ); |
| |
| if (rc != CKR_OK){ |
| st_err_log(104, __FILE__, __LINE__); |
| return rc; |
| } |
| // update the index file if it exists |
| // |
| if ((pw = getpwuid(getuid())) == NULL){ |
| LogError("getpwuid failed: %s", strerror(errno)); |
| return CKR_FUNCTION_FAILED; |
| } |
| |
| sprintf((char *)fname,"%s/%s/%s/%s",(char *)pk_dir, pw->pw_name, |
| PK_LITE_OBJ_DIR, PK_LITE_OBJ_IDX); |
| |
| //sprintf((char *)fname,"%s/%s/%s",pk_dir,PK_LITE_OBJ_DIR,PK_LITE_OBJ_IDX); |
| |
| //fp = fopen( "/tmp/TOK_OBJ/OBJ.IDX", "r" ); |
| fp = fopen( (char *)fname, "r" ); |
| if (fp) { |
| set_perm(fileno(fp)); |
| while (!feof(fp)) { |
| (void)fgets((char *)line, 50, fp ); |
| if (!feof(fp)) { |
| line[ strlen((char *)line)-1 ] = 0; |
| if (strcmp((char *)line,(char *)( obj->name)) == 0) { |
| fclose(fp); |
| return CKR_OK; // object is already in the list |
| } |
| } |
| } |
| fclose(fp); |
| } |
| |
| |
| // we didn't find it...either the index file doesn't exist or this |
| // is a new object... |
| // |
| //fp = fopen("/tmp/TOK_OBJ/OBJ.IDX", "a"); |
| fp = fopen((char *)fname, "a"); |
| if (!fp){ |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| return CKR_FUNCTION_FAILED; |
| } |
| set_perm(fileno(fp)); |
| |
| set_perm(fileno(fp)); |
| fprintf( fp, "%s\n", obj->name ); |
| fclose(fp); |
| |
| return CKR_OK; |
| } |
| |
| |
| // this is the same as the old version. public token objects are stored in the |
| // clear |
| // |
| CK_RV |
| save_public_token_object( OBJECT *obj ) |
| { |
| FILE * fp = NULL; |
| CK_BYTE * cleartxt = NULL; |
| CK_BYTE fname[PATH_MAX]; |
| CK_ULONG cleartxt_len; |
| CK_BBOOL flag = FALSE; |
| CK_RV rc; |
| CK_ULONG_32 total_len; |
| struct passwd *pw = NULL; |
| |
| if ((pw = getpwuid(getuid())) == NULL){ |
| LogError("getpwuid failed: %s", strerror(errno)); |
| return CKR_FUNCTION_FAILED; |
| } |
| |
| sprintf((char *)fname,"%s/%s/%s/",(char *)pk_dir, pw->pw_name, |
| PK_LITE_OBJ_DIR); |
| |
| //strcpy( fname, "/tmp/TOK_OBJ/" ); |
| //sprintf( (char *)fname,"%s/%s/", pk_dir,PK_LITE_OBJ_DIR); |
| strncat( (char *)fname, (char *) obj->name, 8 ); |
| |
| rc = object_flatten( obj, &cleartxt, &cleartxt_len ); |
| if (rc != CKR_OK){ |
| st_err_log(101, __FILE__, __LINE__); |
| goto error; |
| } |
| fp = fopen( (char *)fname, "w" ); |
| if (!fp) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto error; |
| } |
| |
| set_perm(fileno(fp)); |
| |
| total_len = cleartxt_len + sizeof(CK_ULONG_32) + sizeof(CK_BBOOL); |
| |
| (void)fwrite( &total_len, sizeof(CK_ULONG_32), 1, fp ); |
| (void)fwrite( &flag, sizeof(CK_BBOOL), 1, fp ); |
| (void)fwrite( cleartxt, cleartxt_len, 1, fp ); |
| |
| fclose( fp ); |
| free( cleartxt ); |
| |
| return CKR_OK; |
| |
| error: |
| if (fp) fclose( fp ); |
| if (cleartxt) free( cleartxt ); |
| return rc; |
| } |
| |
| |
| // |
| // |
| CK_RV |
| save_private_token_object( OBJECT *obj ) |
| { |
| FILE * fp = NULL; |
| CK_BYTE * obj_data = NULL; |
| CK_BYTE * cleartxt = NULL; |
| CK_BYTE * ciphertxt = NULL; |
| CK_BYTE * ptr = NULL; |
| CK_BYTE fname[100]; |
| CK_BYTE hash_sha[SHA1_HASH_SIZE]; |
| CK_BYTE hash_md5[MD5_HASH_SIZE]; |
| CK_BYTE aes_key[AES_KEY_SIZE_256]; |
| CK_BYTE aes_iv[AES_BLOCK_SIZE]; |
| CK_ULONG obj_data_len,cleartxt_len, ciphertxt_len, hash_len, tmp, tmp2; |
| CK_ULONG padded_len; |
| CK_BBOOL flag; |
| CK_RV rc; |
| CK_ULONG_32 obj_data_len_32; |
| CK_ULONG_32 total_len; |
| struct passwd * pw = NULL; |
| |
| if ((pw = getpwuid(getuid())) == NULL){ |
| LogError("getpwuid failed: %s", strerror(errno)); |
| return CKR_FUNCTION_FAILED; |
| } |
| |
| sprintf((char *)fname,"%s/%s/%s/",(char *)pk_dir, pw->pw_name, |
| PK_LITE_OBJ_DIR); |
| |
| rc = object_flatten( obj, &obj_data, &obj_data_len ); |
| obj_data_len_32 = obj_data_len; |
| if (rc != CKR_OK){ |
| st_err_log(101, __FILE__, __LINE__); |
| goto error; |
| } |
| // |
| // format for the object file: |
| // private flag |
| // ---- begin encrypted part <--+ |
| // length of object data | |
| // object data +---- sensitive part |
| // SHA of (object data) | |
| // ---- end encrypted part <--+ |
| // |
| compute_sha( obj_data, obj_data_len, hash_sha ); |
| |
| // encrypt the sensitive object data. need to be careful. |
| // if I use the normal high-level encryption routines I'll need to |
| // create a tepmorary key object containing the master key, perform the |
| // encryption, then destroy the key object. There is a race condition |
| // here if the application is multithreaded (if a thread-switch occurs, |
| // the other application thread could do a FindObject and be able to access |
| // the master key object. |
| // |
| // So I have to use the low-level encryption routines. |
| // |
| memcpy( aes_key, master_key_private, AES_KEY_SIZE_256 ); |
| memcpy( aes_iv, ")#%&!*)^!()$&!&N", AES_BLOCK_SIZE ); |
| |
| cleartxt_len = sizeof(CK_ULONG_32) + obj_data_len_32 + SHA1_HASH_SIZE; |
| padded_len = AES_BLOCK_SIZE * (cleartxt_len / AES_BLOCK_SIZE + 1); |
| |
| cleartxt = (CK_BYTE *)malloc( padded_len ); |
| ciphertxt = (CK_BYTE *)malloc( padded_len ); |
| if (!cleartxt || !ciphertxt) { |
| st_err_log(0, __FILE__, __LINE__); |
| rc = CKR_HOST_MEMORY; |
| goto error; |
| } |
| |
| ciphertxt_len = padded_len; |
| |
| ptr = cleartxt; |
| memcpy( ptr, &obj_data_len_32, sizeof(CK_ULONG_32) ); ptr += sizeof(CK_ULONG_32); |
| memcpy( ptr, obj_data, obj_data_len_32 ); ptr += obj_data_len_32; |
| memcpy( ptr, hash_sha, SHA1_HASH_SIZE ); |
| |
| add_pkcs_padding( cleartxt + cleartxt_len, AES_BLOCK_SIZE, cleartxt_len, padded_len ); |
| |
| #ifndef CLEARTEXT |
| rc = ckm_aes_cbc_encrypt( cleartxt, padded_len, |
| ciphertxt, &ciphertxt_len, |
| aes_iv, (unsigned char *) aes_key, AES_KEY_SIZE_256 ); |
| #else |
| memcpy(ciphertxt, cleartxt, padded_len); |
| rc = CKR_OK; |
| #endif |
| if (rc != CKR_OK){ |
| st_err_log(105, __FILE__, __LINE__); |
| goto error; |
| } |
| |
| //strcpy( (char *)fname, "/tmp/TOK_OBJ/" ); |
| //sprintf( (char *)fname,"%s/%s/", pk_dir,PK_LITE_OBJ_DIR); |
| strncat( (char *)fname,(char *) obj->name, 8 ); |
| |
| fp = fopen( (char *)fname, "w" ); |
| if (!fp) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto error; |
| } |
| |
| set_perm(fileno(fp)); |
| |
| total_len = sizeof(CK_ULONG_32) + sizeof(CK_BBOOL) + ciphertxt_len; |
| |
| flag = TRUE; |
| |
| (void)fwrite( &total_len, sizeof(CK_ULONG_32), 1, fp ); |
| (void)fwrite( &flag, sizeof(CK_BBOOL), 1, fp ); |
| (void)fwrite( ciphertxt, ciphertxt_len, 1, fp ); |
| |
| fclose( fp ); |
| |
| free( obj_data ); |
| free( cleartxt ); |
| free( ciphertxt ); |
| return CKR_OK; |
| |
| error: |
| if (fp) fclose( fp ); |
| |
| if (obj_data) free( obj_data ); |
| if (cleartxt) free( cleartxt ); |
| if (ciphertxt) free( ciphertxt ); |
| |
| return rc; |
| } |
| |
| |
| // |
| // |
| CK_RV |
| load_public_token_objects( void ) |
| { |
| FILE *fp1 = NULL, *fp2 = NULL; |
| CK_BYTE *buf = NULL; |
| CK_BYTE tmp[PATH_MAX], fname[PATH_MAX], iname[PATH_MAX]; |
| CK_BBOOL priv; |
| CK_ULONG_32 size; |
| CK_RV rc; |
| struct stat fp2_stat; |
| struct passwd *pw = NULL; |
| |
| if ((pw = getpwuid(getuid())) == NULL){ |
| LogError("getpwuid failed: %s", strerror(errno)); |
| return CKR_FUNCTION_FAILED; |
| } |
| |
| sprintf((char *)iname,"%s/%s/%s/%s",(char *)pk_dir, pw->pw_name, |
| PK_LITE_OBJ_DIR, PK_LITE_OBJ_IDX); |
| |
| //sprintf((char *)iname,"%s/%s/%s",pk_dir,PK_LITE_OBJ_DIR, PK_LITE_OBJ_IDX); |
| //fp1 = fopen("/tmp/TOK_OBJ/OBJ.IDX", "r"); |
| fp1 = fopen((char *)iname, "r"); |
| if (!fp1) |
| return CKR_OK; // no token objects |
| |
| while (!feof(fp1)) { |
| (void)fgets( (char *)tmp, 50, fp1 ); |
| if (!feof(fp1)) { |
| tmp[ strlen((char *)tmp)-1 ] = 0; |
| |
| //strcpy(fname,"/tmp/TOK_OBJ/"); |
| sprintf((char *)fname,"%s/%s/%s/",pk_dir, pw->pw_name, PK_LITE_OBJ_DIR); |
| strcat((char *)fname, (char *)tmp ); |
| |
| fp2 = fopen( (char *)fname, "r" ); |
| if (!fp2) |
| continue; |
| |
| // Get the file size for fp2, so we can do sanity checks on |
| // the sizes and skip when the files are corrupted. |
| if ( fstat( fileno(fp2), &fp2_stat ) == -1 ) { |
| LogError( "Unable to stat public token object %s: %s", |
| fname, strerror(errno) ); |
| rc = CKR_FUNCTION_FAILED; |
| goto error; |
| } |
| |
| if ( fread( &size, sizeof(CK_ULONG_32), 1, fp2 ) != 1 || |
| fread( &priv, sizeof(CK_BBOOL), 1, fp2 ) != 1 ) { |
| LogError( "Unable to read public token object %s", fname ); |
| rc = CKR_FUNCTION_FAILED; |
| goto error; |
| } |
| |
| if (priv == TRUE) { |
| fclose( fp2 ); |
| continue; |
| } |
| |
| // If the requested size is larger than the entire file or |
| // smaller than what we've already read, then we know it has |
| // to be bogus. |
| if ( size > fp2_stat.st_size || |
| size < (sizeof(CK_ULONG_32) + sizeof(CK_BBOOL)) ) { |
| LogError( "Corrupt public token object: %s", fname ); |
| rc = CKR_FUNCTION_FAILED; |
| goto error; |
| } |
| |
| // size--; |
| size = size -sizeof(CK_ULONG_32) - sizeof(CK_BBOOL); |
| buf = (CK_BYTE *)malloc(size); |
| if (!buf) { |
| st_err_log(0, __FILE__, __LINE__); |
| rc = CKR_HOST_MEMORY; |
| goto error; |
| } |
| |
| // If the read didn't complete, then the buffer contains at |
| // least some bogus data (and since we know the file is big |
| // enough to read |size| bytes, something else must have |
| // happened). |
| if ( fread( buf, size, 1, fp2 ) != 1 ) { |
| st_err_log( 4, __FILE__, __LINE__, __FUNCTION__ ); |
| rc = CKR_FUNCTION_FAILED; |
| goto error; |
| } |
| |
| // ... grab object mutex here. |
| MY_LockMutex(&obj_list_mutex); |
| object_mgr_restore_obj( buf, NULL ); |
| MY_UnlockMutex(&obj_list_mutex); |
| free( buf ); |
| fclose( fp2 ); |
| } |
| } |
| fclose(fp1); |
| |
| return CKR_OK; |
| |
| error: |
| if (buf) free( buf ); |
| if (fp1) fclose( fp1 ); |
| if (fp2) fclose( fp2 ); |
| return rc; |
| } |
| |
| |
| // |
| // |
| CK_RV |
| load_private_token_objects( void ) |
| { |
| FILE *fp1 = NULL, *fp2 = NULL; |
| CK_BYTE *buf = NULL; |
| CK_BYTE tmp[PATH_MAX], fname[PATH_MAX],iname[PATH_MAX]; |
| CK_BYTE sha_hash[SHA1_HASH_SIZE], old_hash[SHA1_HASH_SIZE]; |
| CK_BBOOL priv; |
| CK_ULONG_32 size; |
| CK_RV rc; |
| struct stat fp2_stat; |
| struct passwd *pw = NULL; |
| |
| if ((pw = getpwuid(getuid())) == NULL){ |
| LogError("getpwuid failed: %s", strerror(errno)); |
| return CKR_FUNCTION_FAILED; |
| } |
| |
| sprintf((char *)iname,"%s/%s/%s/%s",(char *)pk_dir, pw->pw_name, |
| PK_LITE_OBJ_DIR, PK_LITE_OBJ_IDX); |
| |
| //sprintf((char *)iname,"%s/%s/%s",pk_dir,PK_LITE_OBJ_DIR, PK_LITE_OBJ_IDX); |
| //fp1 = fopen("/tmp/TOK_OBJ/OBJ.IDX", "r"); |
| fp1 = fopen((char *)iname, "r"); |
| if (!fp1) |
| return CKR_OK; // no token objects |
| |
| while (!feof(fp1)) { |
| (void)fgets((char *) tmp, 50, fp1 ); |
| if (!feof(fp1)) { |
| tmp[ strlen((char *)tmp)-1 ] = 0; |
| |
| //strcpy(fname,"/tmp/TOK_OBJ/"); |
| sprintf((char *)fname,"%s/%s/%s/",pk_dir, pw->pw_name, PK_LITE_OBJ_DIR); |
| strcat((char *)fname,(char *) tmp ); |
| |
| fp2 = fopen( (char *)fname, "r" ); |
| if (!fp2) |
| continue; |
| |
| // Get the file size for fp2, so we can do sanity checks on |
| // the sizes and skip when the files are corrupted. |
| if (fstat( fileno(fp2), &fp2_stat ) == -1) { |
| LogError( "Unable to stat private token object %s: %s", |
| fname, strerror(errno) ); |
| rc = CKR_FUNCTION_FAILED; |
| goto error; |
| } |
| |
| if ( fread( &size, sizeof(CK_ULONG_32), 1, fp2 ) != 1 || |
| fread( &priv, sizeof(CK_BBOOL), 1, fp2 ) != 1 ) { |
| LogError( "Unable to read private token object %s", fname ); |
| rc = CKR_FUNCTION_FAILED; |
| goto error; |
| } |
| |
| if (priv == FALSE) { |
| fclose( fp2 ); |
| continue; |
| } |
| |
| // If the requested size is larger than the entire file or |
| // smaller than what we've already read, then we know it has |
| // to be bogus. |
| if ( size > fp2_stat.st_size || |
| size < (sizeof(CK_ULONG_32) + sizeof(CK_BBOOL)) ) { |
| LogError( "Corrupt private token object: %s", fname ); |
| rc = CKR_FUNCTION_FAILED; |
| goto error; |
| } |
| |
| //size--; |
| size = size - sizeof(CK_ULONG_32) - sizeof(CK_BBOOL); |
| buf = (CK_BYTE *)malloc(size); |
| if (!buf) { |
| st_err_log(0, __FILE__, __LINE__); |
| rc = CKR_HOST_MEMORY; |
| goto error; |
| } |
| |
| if ( fread( (char *)buf, size, 1, fp2 ) != 1 ) { |
| st_err_log( 4, __FILE__, __LINE__, __FUNCTION__ ); |
| rc = CKR_FUNCTION_FAILED; |
| goto error; |
| } |
| |
| // Grab object list mutex |
| MY_LockMutex(&obj_list_mutex); |
| rc = restore_private_token_object( buf, size, NULL ); |
| MY_UnlockMutex(&obj_list_mutex); |
| if (rc != CKR_OK){ |
| st_err_log(107, __FILE__, __LINE__); |
| goto error; |
| } |
| |
| free( buf ); |
| fclose( fp2 ); |
| } |
| } |
| fclose(fp1); |
| |
| return CKR_OK; |
| |
| error: |
| if (buf) free( buf ); |
| if (fp1) fclose( fp1 ); |
| if (fp2) fclose( fp2 ); |
| return rc; |
| } |
| |
| |
| // |
| // |
| CK_RV |
| restore_private_token_object( CK_BYTE * data, |
| CK_ULONG len, |
| OBJECT * pObj ) |
| { |
| CK_BYTE * cleartxt = NULL; |
| CK_BYTE * obj_data = NULL; |
| CK_BYTE * ciphertxt = NULL; |
| CK_BYTE * ptr = NULL; |
| CK_BYTE aes_key[AES_KEY_SIZE_256]; |
| CK_BYTE aes_iv[AES_BLOCK_SIZE]; |
| CK_BYTE hash_sha[SHA1_HASH_SIZE]; |
| CK_MECHANISM mech; |
| DIGEST_CONTEXT digest_ctx; |
| ENCR_DECR_CONTEXT encr_ctx; |
| CK_ULONG hash_len, cleartxt_len, obj_data_len; |
| CK_RV rc; |
| |
| // format for the object data: |
| // (private flag has already been read at this point) |
| // ---- begin encrypted part |
| // length of object data |
| // object data |
| // SHA of object data |
| // ---- end encrypted part |
| // |
| |
| cleartxt_len = len; |
| |
| cleartxt = (CK_BYTE *)malloc(len); |
| if (!cleartxt) { |
| st_err_log(0, __FILE__, __LINE__); |
| rc = CKR_HOST_MEMORY; |
| goto done; |
| } |
| |
| ciphertxt = data; |
| |
| // decrypt the encrypted chunk |
| // |
| memcpy( aes_key, master_key_private, AES_KEY_SIZE_256 ); |
| memcpy( aes_iv, ")#%&!*)^!()$&!&N", AES_BLOCK_SIZE ); |
| |
| #ifndef CLEARTEXT |
| rc = ckm_aes_cbc_decrypt( ciphertxt, len, |
| cleartxt, &len, |
| aes_iv, aes_key, AES_KEY_SIZE_256 ); |
| #else |
| memcpy(cleartxt, ciphertxt, len); |
| rc = CKR_OK; |
| #endif |
| |
| if (rc != CKR_OK){ |
| st_err_log(106, __FILE__, __LINE__); |
| goto done; |
| } |
| |
| strip_pkcs_padding( cleartxt, len, &cleartxt_len ); |
| |
| // if the padding extraction didn't work it means the object was tampered with or |
| // the key was incorrect |
| // |
| if (cleartxt_len > len) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto done; |
| } |
| |
| ptr = cleartxt; |
| |
| obj_data_len = *(CK_ULONG_32 *)ptr; |
| ptr += sizeof(CK_ULONG_32); |
| obj_data = ptr; |
| |
| // check the hash |
| // |
| compute_sha( ptr, obj_data_len, hash_sha ); |
| ptr += obj_data_len; |
| |
| if (memcmp(ptr, hash_sha, SHA1_HASH_SIZE) != 0) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto done; |
| } |
| |
| // okay. at this point, we're satisfied that nobody has tampered with the |
| // token object... |
| // |
| |
| //object_mgr_restore_obj( obj_data, NULL ); |
| object_mgr_restore_obj( obj_data, pObj ); |
| rc = CKR_OK; |
| |
| done: |
| // if (ciphertxt) free( ciphertxt ); |
| if (cleartxt) free( cleartxt ); |
| |
| return rc; |
| } |
| |
| |
| #if 0 |
| // |
| // |
| CK_RV |
| load_masterkey_so( void ) |
| { |
| FILE * fp = NULL; |
| CK_BYTE * ptr = NULL; |
| CK_BYTE hash_sha[SHA1_HASH_SIZE]; |
| CK_BYTE cipher[sizeof(MASTER_KEY_FILE_T) + DES_BLOCK_SIZE]; |
| CK_BYTE clear [sizeof(MASTER_KEY_FILE_T) + DES_BLOCK_SIZE]; |
| CK_BYTE des3_key[3 * DES_KEY_SIZE]; |
| CK_MECHANISM mech; |
| DIGEST_CONTEXT digest_ctx; |
| MASTER_KEY_FILE_T mk; |
| CK_ULONG cipher_len, clear_len, hash_len; |
| CK_RV rc; |
| CK_BYTE fname[PATH_MAX]; |
| |
| memset( master_key, 0x0, 3*DES_KEY_SIZE ); |
| |
| // this file gets created on C_InitToken so we can assume that it always exists |
| // |
| sprintf((char *)fname,"%s/MK_SO",pk_dir); |
| //fp = fopen("/tmp/MK_SO", "r"); |
| fp = fopen((char *)fname, "r"); |
| if (!fp) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto done; |
| } |
| |
| set_perm(fileno(fp)); |
| clear_len = cipher_len = (sizeof(MASTER_KEY_FILE_T) + DES_BLOCK_SIZE - 1) & ~(DES_BLOCK_SIZE - 1); |
| |
| rc = fread( cipher, cipher_len, 1, fp ); |
| if (rc != 1) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto done; |
| } |
| |
| // decrypt the master key data using the MD5 of the SO key |
| // (we can't use the SHA of the SO key since the SHA of the key is stored |
| // in the token data file). |
| // |
| memcpy( des3_key, so_pin_md5, MD5_HASH_SIZE ); |
| memcpy( des3_key + MD5_HASH_SIZE, so_pin_md5, DES_KEY_SIZE ); |
| |
| #ifndef CLEARTEXT |
| rc = ckm_des3_cbc_decrypt( cipher, cipher_len, clear, &clear_len, "12345678", des3_key ); |
| #else |
| memcpy(clear, cipher, cipher_len); |
| rc = CKR_OK; |
| #endif |
| |
| if (rc != CKR_OK){ |
| st_err_log(106, __FILE__, __LINE__); |
| goto done; |
| } |
| memcpy( (CK_BYTE *)&mk, clear, sizeof(mk) ); |
| |
| // |
| // technically should strip PKCS padding here but since I already know what |
| // the length should be, I don't bother. |
| // |
| |
| |
| // compare the hashes |
| // |
| compute_sha( mk.key, 3 * DES_KEY_SIZE, hash_sha ); |
| |
| if (memcmp(hash_sha, mk.sha_hash, SHA1_HASH_SIZE) != 0) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto done; |
| } |
| |
| memcpy( master_key, mk.key, 3*DES_KEY_SIZE ); |
| rc = CKR_OK; |
| |
| done: |
| if (fp) fclose(fp); |
| return rc; |
| } |
| |
| |
| // |
| // |
| CK_RV |
| load_masterkey_user( void ) |
| { |
| FILE * fp = NULL; |
| CK_BYTE * ptr = NULL; |
| CK_BYTE hash_sha[SHA1_HASH_SIZE]; |
| CK_BYTE cipher[sizeof(MASTER_KEY_FILE_T) + DES_BLOCK_SIZE]; |
| CK_BYTE clear[sizeof(MASTER_KEY_FILE_T) + DES_BLOCK_SIZE]; |
| CK_BYTE des3_key[3 * DES_KEY_SIZE]; |
| CK_MECHANISM mech; |
| DIGEST_CONTEXT digest_ctx; |
| MASTER_KEY_FILE_T mk; |
| CK_ULONG cipher_len, clear_len, hash_len; |
| CK_RV rc; |
| CK_BYTE fname[PATH_MAX]; |
| |
| memset( master_key, 0x0, 3*DES_KEY_SIZE ); |
| |
| // this file gets created on C_InitToken so we can assume that it always exists |
| // |
| sprintf((char *)fname,"%s/MK_USER",pk_dir); |
| //fp = fopen( "/tmp/MK_USER", "r" ); |
| fp = fopen( (char *)fname, "r" ); |
| if (!fp) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto done; |
| } |
| |
| set_perm(fileno(fp)); |
| clear_len = cipher_len = (sizeof(MASTER_KEY_FILE_T) + DES_BLOCK_SIZE - 1) & ~(DES_BLOCK_SIZE - 1); |
| |
| rc = fread( cipher, cipher_len, 1, fp ); |
| if (rc != 1) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto done; |
| } |
| |
| // decrypt the master key data using the MD5 of the SO key |
| // (we can't use the SHA of the SO key since the SHA of the key is stored |
| // in the token data file). |
| // |
| memcpy( des3_key, user_pin_md5, MD5_HASH_SIZE ); |
| memcpy( des3_key + MD5_HASH_SIZE, user_pin_md5, DES_KEY_SIZE ); |
| |
| #ifndef CLEARTEXT |
| rc = ckm_des3_cbc_decrypt( cipher, cipher_len, clear, &clear_len, "12345678", des3_key ); |
| #else |
| memcpy(clear, cipher, cipher_len); |
| rc = CKR_OK; |
| #endif |
| |
| if (rc != CKR_OK){ |
| st_err_log(106, __FILE__, __LINE__); |
| goto done; |
| } |
| memcpy( (CK_BYTE *)&mk, clear, sizeof(mk) ); |
| |
| // |
| // technically should strip PKCS padding here but since I already know what |
| // the length should be, I don't bother. |
| // |
| |
| |
| // compare the hashes |
| // |
| compute_sha( mk.key, 3 * DES_KEY_SIZE, hash_sha ); |
| |
| if (memcmp(hash_sha, mk.sha_hash, SHA1_HASH_SIZE) != 0) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto done; |
| } |
| |
| memcpy( master_key, mk.key, 3*DES_KEY_SIZE ); |
| rc = CKR_OK; |
| |
| done: |
| if (fp) fclose(fp); |
| return rc; |
| } |
| |
| |
| // |
| // |
| CK_RV |
| save_masterkey_so( void ) |
| { |
| FILE * fp = NULL; |
| CK_BYTE cleartxt [sizeof(MASTER_KEY_FILE_T) + DES_BLOCK_SIZE]; |
| CK_BYTE ciphertxt[sizeof(MASTER_KEY_FILE_T) + DES_BLOCK_SIZE]; |
| CK_BYTE des3_key[3 * DES_KEY_SIZE]; |
| CK_MECHANISM mech; |
| DIGEST_CONTEXT digest_ctx; |
| MASTER_KEY_FILE_T mk; |
| CK_ULONG hash_len, cleartxt_len, ciphertxt_len, padded_len; |
| CK_RV rc; |
| CK_BYTE fname[PATH_MAX]; |
| |
| |
| memcpy( mk.key, master_key, 3 * DES_KEY_SIZE); |
| |
| compute_sha( master_key, 3 * DES_KEY_SIZE, mk.sha_hash ); |
| |
| // encrypt the key data |
| // |
| memcpy( des3_key, so_pin_md5, MD5_HASH_SIZE ); |
| memcpy( des3_key + MD5_HASH_SIZE, so_pin_md5, DES_KEY_SIZE ); |
| |
| ciphertxt_len = sizeof(ciphertxt); |
| cleartxt_len = sizeof(mk); |
| memcpy( cleartxt, &mk, cleartxt_len ); |
| |
| padded_len = DES_BLOCK_SIZE * (cleartxt_len / DES_BLOCK_SIZE + 1); |
| add_pkcs_padding( cleartxt + cleartxt_len, DES_BLOCK_SIZE, cleartxt_len, padded_len ); |
| |
| #ifndef CLEARTEXT |
| rc = ckm_des3_cbc_encrypt( cleartxt, padded_len, ciphertxt, &ciphertxt_len, "12345678", des3_key ); |
| #else |
| memcpy(ciphertxt, cleartxt, padded_len); |
| rc = CKR_OK; |
| #endif |
| |
| if (rc != CKR_OK){ |
| st_err_log(105, __FILE__, __LINE__); |
| goto done; |
| } |
| |
| // write the file |
| // |
| // probably ought to ensure the permissions are correct |
| // |
| sprintf((char *)fname,"%s/MK_SO",pk_dir); |
| //fp = fopen( "/tmp/MK_SO", "w" ); |
| fp = fopen( (char *)fname, "w" ); |
| if (!fp) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto done; |
| } |
| set_perm(fileno(fp)); |
| |
| rc = fwrite( ciphertxt, ciphertxt_len, 1, fp ); |
| if (rc != 1) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto done; |
| } |
| |
| rc = CKR_OK; |
| |
| done: |
| if (fp) fclose( fp ); |
| return rc; |
| } |
| |
| |
| // |
| // |
| CK_RV |
| save_masterkey_user( void ) |
| { |
| FILE * fp = NULL; |
| CK_BYTE cleartxt [sizeof(MASTER_KEY_FILE_T) + DES_BLOCK_SIZE]; |
| CK_BYTE ciphertxt[sizeof(MASTER_KEY_FILE_T) + DES_BLOCK_SIZE]; |
| CK_BYTE des3_key[3 * DES_KEY_SIZE]; |
| CK_MECHANISM mech; |
| DIGEST_CONTEXT digest_ctx; |
| MASTER_KEY_FILE_T mk; |
| CK_ULONG hash_len, cleartxt_len, ciphertxt_len, padded_len; |
| CK_RV rc; |
| CK_BYTE fname[PATH_MAX]; |
| |
| |
| memcpy( mk.key, master_key, 3 * DES_KEY_SIZE); |
| |
| compute_sha( master_key, 3 * DES_KEY_SIZE, mk.sha_hash ); |
| |
| |
| // encrypt the key data |
| // |
| memcpy( des3_key, user_pin_md5, MD5_HASH_SIZE ); |
| memcpy( des3_key + MD5_HASH_SIZE, user_pin_md5, DES_KEY_SIZE ); |
| |
| ciphertxt_len = sizeof(ciphertxt); |
| cleartxt_len = sizeof(mk); |
| memcpy( cleartxt, &mk, cleartxt_len ); |
| |
| padded_len = DES_BLOCK_SIZE * (cleartxt_len / DES_BLOCK_SIZE + 1); |
| add_pkcs_padding( cleartxt + cleartxt_len, DES_BLOCK_SIZE, cleartxt_len, padded_len ); |
| |
| #ifndef CLEARTEXT |
| rc = ckm_des3_cbc_encrypt( cleartxt, padded_len, ciphertxt, &ciphertxt_len, "12345678", des3_key ); |
| #else |
| memcpy(ciphertxt, cleartxt, padded_len); |
| rc = CKR_OK; |
| #endif |
| |
| if (rc != CKR_OK){ |
| st_err_log(105, __FILE__, __LINE__); |
| goto done; |
| } |
| |
| |
| // write the file |
| // |
| // probably ought to ensure the permissions are correct |
| // |
| sprintf((char *)fname,"%s/MK_USER", pk_dir); |
| //fp = fopen( "/tmp/MK_USER", "w" ); |
| fp = fopen( (char *)fname, "w" ); |
| if (!fp) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto done; |
| } |
| |
| set_perm(fileno(fp)); |
| rc = fwrite( ciphertxt, ciphertxt_len, 1, fp ); |
| if (rc != 1) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto done; |
| } |
| |
| rc = CKR_OK; |
| |
| done: |
| if (fp) fclose( fp ); |
| return rc; |
| } |
| #endif |
| |
| // |
| // |
| CK_RV |
| reload_token_object( OBJECT *obj ) |
| { |
| FILE * fp = NULL; |
| CK_BYTE * buf = NULL; |
| CK_BYTE fname[PATH_MAX]; |
| CK_BBOOL priv; |
| CK_ULONG_32 size; |
| CK_ULONG size_64; |
| CK_RV rc; |
| struct passwd *pw = NULL; |
| |
| if ((pw = getpwuid(getuid())) == NULL){ |
| LogError("getpwuid failed: %s", strerror(errno)); |
| return CKR_FUNCTION_FAILED; |
| } |
| |
| memset( (char *)fname, 0x0, sizeof(fname) ); |
| |
| sprintf((char *)fname,"%s/%s/%s/",(char *)pk_dir, pw->pw_name, |
| PK_LITE_OBJ_DIR); |
| |
| // strcpy(fname, "/tmp/TOK_OBJ/" ); |
| //sprintf((char *)fname,"%s/%s/",pk_dir, PK_LITE_OBJ_DIR); |
| strncat((char *)fname,(char *) obj->name, 8 ); |
| |
| fp = fopen( (char *)fname, "r" ); |
| if (!fp) { |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| rc = CKR_FUNCTION_FAILED; |
| goto done; |
| } |
| |
| set_perm(fileno(fp)); |
| |
| fread( &size, sizeof(CK_ULONG_32), 1, fp ); |
| fread( &priv, sizeof(CK_BBOOL), 1, fp ); |
| |
| size = size - sizeof(CK_ULONG_32) - sizeof(CK_BBOOL); // SAB |
| |
| buf = (CK_BYTE *)malloc(size); |
| if (!buf) { |
| st_err_log(0, __FILE__, __LINE__); |
| rc = CKR_HOST_MEMORY; |
| goto done; |
| } |
| |
| fread( buf, size, 1, fp ); |
| |
| size_64 = size; |
| |
| if (priv){ |
| rc = restore_private_token_object( buf, size_64, obj ); |
| if (rc != CKR_OK) |
| st_err_log(107, __FILE__, __LINE__); |
| } |
| else{ |
| rc = object_mgr_restore_obj( buf, obj ); |
| if (rc != CKR_OK) |
| st_err_log(108, __FILE__, __LINE__); |
| } |
| |
| done: |
| if (fp) fclose( fp ); |
| if (buf) free( buf ); |
| return rc; |
| } |
| |
| |
| |
| extern void set_perm(int) ; |
| |
| // |
| // |
| CK_RV |
| delete_token_object( OBJECT *obj ) |
| { |
| FILE *fp1, *fp2; |
| CK_BYTE line[100]; |
| CK_BYTE objidx[PATH_MAX], idxtmp[PATH_MAX], fname[PATH_MAX]; |
| struct passwd *pw = NULL; |
| |
| if ((pw = getpwuid(getuid())) == NULL){ |
| LogError("getpwuid failed: %s", strerror(errno)); |
| return CKR_FUNCTION_FAILED; |
| } |
| |
| sprintf((char *)objidx,"%s/%s/%s/%s",(char *)pk_dir, pw->pw_name, |
| PK_LITE_OBJ_DIR, PK_LITE_OBJ_IDX); |
| sprintf((char *)idxtmp,"%s/%s/%s/%s",(char *)pk_dir, pw->pw_name, |
| PK_LITE_OBJ_DIR, "IDX.TMP"); |
| |
| |
| // FIXME: on UNIX, we need to make sure these guys aren't symlinks |
| // before we blindly write to these files... |
| // |
| |
| // remove the object from the index file |
| // |
| |
| //sprintf((char *)objidx,"%s/%s/%s",pk_dir, PK_LITE_OBJ_DIR,PK_LITE_OBJ_IDX); |
| //sprintf((char *)idxtmp,"%s/%s/%s",pk_dir, PK_LITE_OBJ_DIR, "IDX.TMP"); |
| //fp1 = fopen("/tmp/TOK_OBJ/OBJ.IDX", "r"); |
| //fp2 = fopen("/tmp/TOK_OBJ/IDX.TMP", "w"); |
| fp1 = fopen((char *)objidx, "r"); |
| fp2 = fopen((char *)idxtmp, "w"); |
| if (!fp1 || !fp2) { |
| if (fp1) fclose(fp1); |
| if (fp2) fclose(fp2); |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| return CKR_FUNCTION_FAILED; |
| } |
| |
| set_perm(fileno(fp2)); |
| |
| while (!feof(fp1)) { |
| (void)fgets((char *)line, 50, fp1 ); |
| if (!feof(fp1)) { |
| line[ strlen((char *)line)-1 ] = 0; |
| if (strcmp((char *)line, (char *)obj->name) == 0) |
| continue; |
| else |
| fprintf( fp2, "%s\n", line ); |
| } |
| } |
| |
| fclose(fp1); |
| fclose(fp2); |
| //fp2 = fopen("/tmp/TOK_OBJ/OBJ.IDX", "w"); |
| //fp1 = fopen("/tmp/TOK_OBJ/IDX.TMP", "r"); |
| fp2 = fopen((char *)objidx, "w"); |
| fp1 = fopen((char *)idxtmp, "r"); |
| if (!fp1 || !fp2) { |
| if (fp1) fclose(fp1); |
| if (fp2) fclose(fp2); |
| st_err_log(4, __FILE__, __LINE__, __FUNCTION__); |
| return CKR_FUNCTION_FAILED; |
| } |
| |
| set_perm(fileno(fp2)); |
| |
| while (!feof(fp1)) { |
| (void)fgets((char *)line, 50, fp1 ); |
| if (!feof(fp1)) |
| fprintf( fp2, "%s",(char *) line ); |
| } |
| |
| fclose(fp1); |
| fclose(fp2); |
| |
| sprintf((char *)fname,"%s/%s/%s/%s",pk_dir, pw->pw_name, PK_LITE_OBJ_DIR, (char *)obj->name); |
| //sprintf((char *)fname,"%s/%s/%s",pk_dir, PK_LITE_OBJ_DIR,(char *)obj->name); |
| unlink((char *)fname); |
| return CKR_OK; |
| |
| } |
| |