1/*- 2 * Copyright (C) 2001-2003 by NBMK Encryption Technologies. 3 * All rights reserved. 4 * 5 * NBMK Encryption Technologies provides no support of any kind for 6 * this software. Questions or concerns about it may be addressed to 7 * the members of the relevant open-source community at 8 * <tech-crypto@netbsd.org>. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions are 12 * met: 13 * 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 17 * 2. Redistributions in binary form must reproduce the above 18 * copyright notice, this list of conditions and the following 19 * disclaimer in the documentation and/or other materials provided 20 * with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35static char const n8_id[] = "$Id: n8_sks.c,v 1.2 2011/08/01 12:28:54 mbalmer Exp $"; 36/*****************************************************************************/ 37/** @file SKS_Management_Interface 38 * @brief Implementation for the SKS Management Interface. 39 * 40 * Allows for the initialization and subsequent key management of associated 41 * SKS PROMs. 42 * 43 *****************************************************************************/ 44 45 46/***************************************************************************** 47 * Revision history: 48 * 49 * 02/10/04 bac Fixed N8_SKSReset bug (Bug 1006) by changing test logic. 50 * 06/06/03 brr Move n8_enums to public include as n8_pub_enums. 51 * 05/16/03 brr Eliminate obsolete include file. 52 * 04/04/02 bac Reformat to conform to coding standards. 53 * 04/01/02 spm Moved deletion of key handle files from n8_SKSResetUnit 54 * ioctl to N8_SKSReset API call. 55 * 03/04/02 spm N8_GetSKSKeyHandle changed to set the value of the unit to 56 * N8_ANY_UNIT if N8_SKS_ROUND_ROBIN is defined. (Bug 645) 57 * Fixed N8_SKSGetKeyHandle so that it now copies the passed 58 * entry name into the entry_name field in the key handle. 59 * 03/18/02 bac Made all public entry points execute the preamble to ensure 60 * the API and chip are initialized. 61 * 02/28/02 brr Do not include any QMgr include files. 62 * 02/22/02 spm Added include of n8_time.h. Converted N8_KPRINT's to DBG's. 63 * 02/20/02 brr Removed references to the queue structure. 64 * 02/14/02 brr Reconcile 2.0 memory management modifications. 65 * 02/05/02 spm Removed #include of <linux/string.h> and 66 * restored #include of n8_OS_intf.h. 67 * 01/28/02 spm Changed while loops in SKS write to n8_usleeps. 68 * A test is made after the sleep has completed to 69 * insure that the go busy flag is cleared by the 70 * hardware. Added break to N8_SKSGetKeyHandle for loop 71 * for the case that the file is found. 72 * 01/22/02 spm Moved n8_ComputeKeyLength to n8_sks_util.c. 73 * 01/22/02 spm Moved n8_SKSInitialize ot n8_sksInit.c. 74 * 01/20/02 spm Removed system calls. Replaced file system handling 75 * with requests to the N8 daemon. 76 * 01/17/02 bac Bug #480 -- SKS write caused persistent N8_HARDWARE_ERROR. 77 * Cleared any existing error flags before the write. Also 78 * expanded the critical section to include the subsequent wait 79 * for no busy. 80 * 01/07/02 bac Fixed semaphore usage to prevent deadlock. Bug #450. 81 * 12/20/01 bac Removed global SKS_Descriptor management array and now use 82 * shared memory in the Queue Control structure. Bug #436. 83 * 12/11/01 mel Fixed bug #414: Added checks for NULL 84 * 12/07/01 bac Fixed merging issues. N8_SKSFree now, definitively, only 85 * takes a handle and not also an entry name. 86 * 12/07/01 bac Made N8_SKSReset more efficient by only calling SKSWrite once, 87 * free and reclaim entries if a new allocation has the same 88 * name, fixed abug in SKSWrite to force it to wait until 89 * finished before proceeding. 90 * 12/03/01 bac Rearrange order of write to SKS/write file in order to write 91 * the file first and return an error if it does not occur. 92 * Failures on write to the SKS cause the files to be removed. 93 * (BUG #391) 94 * 11/29/01 bac Added closedir() as needed to avoid leaking directory 95 * descriptors. (BUG #385). Also allowed the use of N8_ANY_UNIT 96 * on calls to N8_SKSReset. (BUG #386). 97 * 12/03/01 mel Fixed bug #395: in DBG string changed % to %% - to eliminate 98 * compilation error 99 * 11/19/01 bac Reworked the DSA key constraint testing. Fixed 100 * N8_SKSGetKeyHandle to use the full path name. Corrected the 101 * computation of the number of SKS words used by pre-existing 102 * entries so that they not be over-written. Changed 103 * N8_SKSAllocate[RSA|DSA] to accept N8_ANY_KEY as unit 104 * specifiers. 105 * Bugs #347, 352, 362, 355, 358, 361, 356, 359, 354, 357, 360. 106 * 11/16/01 mel Fixed bug #346: N8_SKSReset memory faults when invalid(-2) 107 * TargetSKS paramter is entered 108 * 11/16/01 mel Fixed bug #349: N8_SKSDisplay formatted output could be 109 * printed better. 110 * 11/16/01 mel Fixed bug #348: N8_SKSDisplay memory faults when NULL Pointer 111 * for 1st parameter 112 * 11/16/01 mel Fixed bug #345: N8_SKSFree command returns 113 * N8_UNEXPECTED_ERROR instead of N8_INVALID_KEY 114 * 11/16/01 mel Fixed bug #344: N8_SKSFree with NULL pointer to 115 * N8_SKSKeyHandle_t parameter causes a memory fault 116 * 11/15/01 mel Fixed bug #332: N8_AllocateRSA returns N8_INVALID_OBJECT 117 * instead of N8_INVALID_KEY_SIZE when p.length != q.length 118 * 11/15/01 bac Changed all fprintf(stderrr,...) to DBG() 119 * 11/15/01 mel Fixed bug #330: N8_AllocateRSA seg faults when pointer to 120 * privateKey value is NULL 121 * 11/15/01 mel Fixed bug #329: N8_SKSAllocateRSA memory faults when pointer 122 * to KeyMaterial is NULL 123 * 11/15/01 mel Fixed bug #331: N8_SKSAllocateRSA returns N8_HARDWARE_ERROR 124 * when p.lengthBtyes of q.lengthBytes= 0 125 * 11/14/01 spm Changed prom-to-cache copy fn to work with new register 126 * access macros. 127 * 11/13/01 mel Fixed bug #297: register access macros in n8_sks.c will 128 * only work on the behavioral model 129 * 11/13/01 bac Close all file descriptors when finished with them. 130 * 11/10/01 spm Added SKS prom-to-cache copy routine for use by 131 * QMgr setup. Addressed bug #295 with a comment. 132 * 11/08/01 mel Fixed bug #302: No call to N8_preamble in the n8_sks.c API routines. 133 * 11/04/01 bac Propogate return codes rather than masking them with 134 * N8_UNEXPECTED_ERROR and changed the mode on the call to 135 * mkdir to allow group write access. 136 * 10/30/01 dkm Eliminate warning in VxWorks 137 * 10/22/01 bac Fixed problems calculating free blocks. 138 * 10/19/01 hml Fixed some compiler warnings. 139 * 10/14/01 bac Included string.h to silence compiler warning. 140 * 10/11/01 bac Changed parameters passed to Param_Byte_Length macros to 141 * reflect their new definitions. 142 * 10/10/01 jdj Multi-thread safe semaphores added to file and register 143 * accesses. 144 * 10/09/01 msz Minor changes to calls to opendir and mkdir so they compile 145 * without warnings under vxworks. VxWorks has different 146 * args for mkdir, and doesn't preserve const. 147 * 06/04/01 jdj Original version. 148 ****************************************************************************/ 149/** @defgroup n8_sks SKS Management Interface 150 */ 151 152#include "n8_sks.h" 153#include "n8_pub_sks.h" 154#include "n8_rsa.h" 155#include "n8_dsa.h" 156#include "n8_util.h" 157#include "n8_pub_enums.h" 158#include "n8_driver_api.h" 159#include "n8_API_Initialize.h" 160#include "n8_device_info.h" 161 162#include "n8_OS_intf.h" 163#include "n8_semaphore.h" 164#include "n8_daemon_sks.h" 165#include "n8_sks_util.h" 166#include "n8_time.h" 167#include "n8_SKSManager.h" 168 169extern NSPdriverInfo_t nspDriverInfo; 170 171/* Local method prototypes */ 172#ifdef N8DEBUG 173void n8_printSKSKeyHandle(const N8_SKSKeyHandle_t *keyHandle_p); 174#endif 175 176/* Local methods */ 177 178/***************************************************************************** 179 * n8_getNumUnits 180 *****************************************************************************/ 181/** @ingroup n8_sks 182 * @brief Returns how many units (chips) there are in the system. 183 * 184 * @param 185 * None 186 * 187 * @par Externals 188 * nspDriverInfo 189 * 190 * @return 191 * Number of units. 192 * 193 * @par Errors 194 * None 195 * 196 * @par Assumptions 197 * Driver has been opened. 198 * 199 *****************************************************************************/ 200 201static int n8_getNumUnits(void) 202{ 203 204 return nspDriverInfo.numChips; 205 206} /* n8_getNumUnits */ 207 208 209/***************************************************************************** 210 * n8_checkAndFreeEntry 211 *****************************************************************************/ 212/** @ingroup n8_sks 213 * @brief Check to see if a named entry exists and if so free it. 214 * 215 * If a request is made to allocate an entry for a tuple <unit, name> and it 216 * already exists, then we replace it. First we look for the named entry and 217 * delete it if it exists. This allows the harvesting of resources before the 218 * re-allocation to ensure no resources are lost. 219 * 220 * @param name RO: name of entry 221 * @param unit RO: unit identifier 222 * 223 * @par Externals 224 * None 225 * 226 * @return 227 * Status 228 * 229 * @par Errors 230 * None 231 * 232 * @par Assumptions 233 * None 234 *****************************************************************************/ 235 236static N8_Status_t n8_checkAndFreeEntry(const N8_Buffer_t *name, const N8_Unit_t unit) 237{ 238 N8_Status_t ret; 239 N8_SKSKeyHandle_t tempHandle; 240 241 tempHandle.unitID = unit; 242 ret = N8_SKSGetKeyHandle(name, &tempHandle); 243 244 if (ret == N8_STATUS_OK) 245 { 246#if N8_SKS_ROUND_ROBIN 247 /* If we are using round robin algorithm, then N8_SKS_GetKeyHandle will force 248 * the key handle unit ID to N8_ANY_UNIT (-1). We must restore the unit ID 249 * to its original value in this case. 250 */ 251 tempHandle.unitID = unit; 252#endif 253 /* an entry of this name exists. free it and reclaim the resources. */ 254 ret = N8_SKSFree(&tempHandle); 255 } 256 else 257 { 258 ret = N8_STATUS_OK; 259 } 260 return ret; 261} 262 263/***************************************************************************** 264 * n8_verifyUnitID 265 *****************************************************************************/ 266/** @ingroup n8_sks 267 * @brief Given a unit ID, verify that it is valid. If N8_ANY_UNIT is 268 * specified, then have the QMgr select one to use. 269 * 270 * @param unit RO: unit ID to be verified 271 * @param keyHandle_p RW: SKSKeyHandle to place the results 272 * 273 * @par Externals 274 * None 275 * 276 * @return 277 * Status 278 * 279 * @par Errors 280 * N8_INVALID_VALUE if the unit id is out of range. 281 * 282 * @par Assumptions 283 * None 284 *****************************************************************************/ 285static N8_Status_t 286n8_verifyUnitID(const N8_Unit_t unit, N8_SKSKeyHandle_t *keyHandle_p) 287{ 288 int numSKS; 289 static int sksSelection = 0; 290 291 /* get the number of units */ 292 numSKS = n8_getNumUnits(); 293 294 /* TODO: We are selecting a unit number here. It should be done in */ 295 /* QMgr. However, it appeared that we might first need to select a */ 296 /* unit in this code, so we can check if the file exists, and the */ 297 /* filename is based on the unit id. So, for now, we will select a */ 298 /* valid unit ID here, and return it. In the future it would be */ 299 /* perhaps better to have the write return what unit was selected. */ 300 if (unit == N8_ANY_UNIT) 301 { 302 keyHandle_p->unitID = sksSelection; 303 sksSelection = sksSelection + 1; 304 if (sksSelection == numSKS) 305 { 306 sksSelection = 0; 307 } 308 } 309 else if ((unit < 0) || (unit >= numSKS)) 310 { 311 return N8_INVALID_VALUE; 312 } 313 else 314 { 315 keyHandle_p->unitID = unit; 316 } 317 318 return N8_STATUS_OK; 319} 320 321#ifdef N8DEBUG 322/***************************************************************************** 323 * n8_printSKSKeyHandle 324 *****************************************************************************/ 325/** @ingroup n8_sks 326 * @brief Display a key handle for an SKS PROM. 327 * 328 * @param keyHandle_p RO: A pointer to the key handle to be printed. 329 * 330 * @par Externals: 331 * None 332 * 333 * @return 334 * None. 335 * 336 * @par Errors: 337 * None. 338 * 339 * @par Assumptions: 340 * None. 341 *****************************************************************************/ 342void n8_printSKSKeyHandle(const N8_SKSKeyHandle_t *keyHandle_p) 343{ 344 345 DBG(("Key Handle:\n")); 346 DBG(("Key Type %08x\n", 347 keyHandle_p->key_type)); 348 DBG(("Key Length %08x\n\tSKS Offset %08x\n", 349 keyHandle_p->key_length, 350 keyHandle_p->sks_offset)); 351 DBG(("Target SKS %08x\n", 352 keyHandle_p->unitID)); 353} /* n8_printSKSKeyHandle */ 354#endif 355 356/* Public methods */ 357 358/***************************************************************************** 359 * N8_SKSDisplay 360 *****************************************************************************/ 361/** @ingroup n8_sks 362 * @brief Display a description entity for an SKS PROM. 363 * 364 * Attempts to write a string into a given char string array. 365 * 366 * @param keyHandle_p RW: A N8_SKSKeyHandle_t pointer. 367 * @param display_string RO: A char array. 368 * 369 * @par Externals: 370 * external_var1 RW: A Read Write external variable<BR> 371 * external_var2 RO: A Read Only external variable<BR> 372 * external_var3 WO: A Write Only external variable: No "break" on last one. 373 * 374 * @return 375 * N8_STATUS_OK if no other errors. The display contents should now be 376 * within the provided char array. 377 * 378 * @par Assumptions: 379 * The given key handle pointer is valid. 380 *****************************************************************************/ 381N8_Status_t N8_SKSDisplay(N8_SKSKeyHandle_t *keyHandle_p, 382 char *display_string_p) 383{ 384 if (keyHandle_p == NULL) 385 { 386 return N8_INVALID_KEY; 387 } 388 389 if (display_string_p == NULL) 390 { 391 return N8_INVALID_PARAMETER; 392 } 393 394 sprintf(display_string_p, 395 "Key Handle:\n" 396 "\tKey Type %08x\n" 397 "\tKey Length %08x\n" 398 "\tSKS Offset %08x\n" 399 "\tTarget SKS %08x\n", 400 keyHandle_p->key_type, keyHandle_p->key_length, 401 keyHandle_p->sks_offset, keyHandle_p->unitID); 402 403 return N8_STATUS_OK; 404} /* N8_SKSDisplay */ 405 406 407/***************************************************************************** 408 * N8_SKSAllocateRSA 409 *****************************************************************************/ 410/** @ingroup n8_sks 411 * @brief Allocate and write a private RSA key entry to an SKS PROM. 412 * 413 * Attempts to allocate, then write the key into an SKS PROM. 414 * 415 * @param keyMaterial_p RW: A N8_RSAKeyMaterial_t pointer. 416 * @param keyEntryName_p RW: A char pointer, the name of the sks entry. 417 * 418 * @par Externals: 419 * None 420 * 421 * @return 422 * N8_STATUS_OK indicates the key allocation and write successfully completed. 423 * N8_UNEXPECTED_ERROR indicates an error writing the key handle or that 424 * the API was not or could not be initialized. 425 * 426 * @par Assumptions: 427 * That the RSA key material pointer is valid. 428 *****************************************************************************/ 429N8_Status_t N8_SKSAllocateRSA(N8_RSAKeyMaterial_t *keyMaterial_p, 430 const N8_Buffer_t *keyEntryName_p) 431{ 432 N8_RSAKeyObject_t key; 433 N8_Buffer_t* param; 434 435 uint32_t sksOffset = 0, targetSKS = 0, keyLength = 0; 436 N8_Status_t ret = N8_STATUS_OK; 437 N8_SKSKeyHandle_t *sks_key_p; 438 439 do 440 { 441 ret = N8_preamble(); 442 CHECK_RETURN(ret); 443 CHECK_OBJECT(keyMaterial_p, ret); 444 CHECK_OBJECT(keyMaterial_p->privateKey.value_p, ret); 445 446 CHECK_OBJECT(keyEntryName_p, ret); 447 if (strlen(keyEntryName_p) >= N8_SKS_ENTRY_NAME_MAX_LENGTH) 448 { 449 ret = N8_INVALID_OBJECT; 450 break; 451 } 452 if ((keyMaterial_p->p.lengthBytes == 0) || 453 (keyMaterial_p->q.lengthBytes == 0)) 454 { 455 ret = N8_INVALID_KEY_SIZE; 456 break; 457 } 458 459 sks_key_p = &keyMaterial_p->SKSKeyHandle; 460 461 ret = n8_verifyUnitID(keyMaterial_p->unitID, sks_key_p); 462 CHECK_RETURN(ret); 463 464 /* Check requirements for p and q lengths. */ 465 466 /* len(p) == len(q) */ 467 if (keyMaterial_p->q.lengthBytes != keyMaterial_p->p.lengthBytes) 468 { 469 DBG(("P and Q RSA key material parameters not of same length!\n")); 470 ret = N8_INVALID_KEY_SIZE; 471 break; 472 } 473 /* len(p) == len(q) == 1/2 len(private key). note we don't perform the 474 * division in the test as integer division would round down. */ 475 if ((keyMaterial_p->q.lengthBytes * 2) != 476 keyMaterial_p->privateKey.lengthBytes) 477 { 478 DBG(("P and Q RSA key material parameter length not half of " 479 "private key length!\n")); 480 ret = N8_INVALID_KEY_SIZE; 481 break; 482 } 483 484 /* public key length mod 32 == 0 or 17-31 */ 485 if (keyMaterial_p->privateKey.lengthBytes % 32 != 0 && 486 keyMaterial_p->privateKey.lengthBytes % 32 <= 16) 487 { 488 DBG(("Private key length %% 32 is not in the valid range of 0 or 17-31.\n")); 489 ret = N8_INVALID_KEY_SIZE; 490 break; 491 } 492 493 /* check to see if an entry of this name already exists and free 494 * it if so. */ 495 ret = n8_checkAndFreeEntry(keyEntryName_p, keyMaterial_p->SKSKeyHandle.unitID); 496 CHECK_RETURN(ret); 497 498 ret = N8_RSAInitializeKey(&key, N8_PRIVATE_CRT, keyMaterial_p, NULL); 499 CHECK_RETURN(ret); 500 501 keyLength = keyMaterial_p->privateKey.lengthBytes; 502 targetSKS = sks_key_p->unitID; 503 sks_key_p->key_type = N8_RSA_VERSION_1_KEY; 504 505 /* The key length field of the key handle is always in BNC digits. */ 506 sks_key_p->key_length = 507 BYTES_TO_PKDIGITS(keyLength); 508 509 DBG(("Key Length in bytes: %d\n", keyLength)); 510 DBG(("Key length in digits: %d\n", sks_key_p->key_length)); 511 512 ret = n8_SKSAllocate(sks_key_p); 513 CHECK_RETURN(ret); 514 515 /* attempt to write the key information to the mapping files */ 516 strcpy(sks_key_p->entry_name, keyEntryName_p); 517 518 /* request N8 userspace daemon to write out a key handle file */ 519 ret = n8_daemon_sks_write(sks_key_p, keyEntryName_p); 520 521 if (ret != N8_STATUS_OK) 522 { 523 /* the write to the key handle failed. 524 * we need to unallocate the space 525 * and return a failure. */ 526 527 DBG(("n8_daemon_sks_write returned error\n")); 528 529 n8_SKSsetStatus(sks_key_p, SKS_FREE); 530 break; 531 } 532 533 sksOffset = sks_key_p->sks_offset; 534 535 /* Write the data into the SKS PROM. */ 536 DBG(("Writing key data into SKS.\n")); 537 538 /* Write the p value into the SKS. */ 539 DBG(("Writing p param into SKS.\n")); 540 541 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress + 542 PK_RSA_P_Param_Byte_Offset(&key); 543 544 ret = n8_SKSWrite(targetSKS, 545 (uint32_t*) param, 546 SKS_RSA_P_LENGTH(sks_key_p->key_length), 547 sksOffset + 548 SKS_RSA_P_OFFSET(sks_key_p->key_length), 549 FALSE); 550 DBG(("Return from write: %s\n", N8_Status_t_text(ret))); 551 CHECK_RETURN(ret); 552 553 /* Write the p value into the SKS. */ 554 DBG(("Writing q param into SKS.\n")); 555 556 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress + 557 PK_RSA_Q_Param_Byte_Offset(&key); 558 559 ret = n8_SKSWrite(targetSKS, 560 (uint32_t*) param, 561 SKS_RSA_Q_LENGTH(sks_key_p->key_length), 562 sksOffset + 563 SKS_RSA_Q_OFFSET(sks_key_p->key_length), 564 FALSE); 565 DBG(("Return from write: %s\n", N8_Status_t_text(ret))); 566 CHECK_RETURN(ret); 567 568 /* Write the dp value into the SKS. */ 569 DBG(("Writing dp param into SKS.\n")); 570 571 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress + 572 PK_RSA_DP_Param_Byte_Offset(&key); 573 574 ret = n8_SKSWrite(targetSKS, 575 (uint32_t*) param, 576 SKS_RSA_DP_LENGTH(sks_key_p->key_length), 577 sksOffset + 578 SKS_RSA_DP_OFFSET(sks_key_p->key_length), 579 FALSE); 580 581 DBG(("Return from write: %s\n", N8_Status_t_text(ret))); 582 CHECK_RETURN(ret); 583 584 585 /* Write the dq value into the SKS. */ 586 DBG(("Writing dq param into SKS.\n")); 587 588 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress + 589 PK_RSA_DQ_Param_Byte_Offset(&key); 590 591 ret = n8_SKSWrite(targetSKS, 592 (uint32_t*) param, 593 SKS_RSA_DQ_LENGTH(sks_key_p->key_length), 594 sksOffset + 595 SKS_RSA_DQ_OFFSET(sks_key_p->key_length), 596 FALSE); 597 DBG(("Return from write: %s\n", N8_Status_t_text(ret))); 598 CHECK_RETURN(ret); 599 600 /* Write the R mod p value into the SKS. */ 601 DBG(("Writing R mod p param into SKS.\n")); 602 603 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress + 604 PK_RSA_R_MOD_P_Param_Byte_Offset(&key); 605 606 607 ret = 608 n8_SKSWrite(targetSKS, 609 (uint32_t*) param, 610 SKS_RSA_RMODP_LENGTH(sks_key_p->key_length), 611 sksOffset + 612 SKS_RSA_RMODP_OFFSET(sks_key_p->key_length), 613 FALSE); 614 DBG(("Return from write: %s\n", N8_Status_t_text(ret))); 615 CHECK_RETURN(ret); 616 617 /* Write the R mod q value into the SKS. */ 618 DBG(("Writing R mod q param into SKS.\n")); 619 620 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress + 621 PK_RSA_R_MOD_Q_Param_Byte_Offset(&key); 622 623 ret = 624 n8_SKSWrite(targetSKS, 625 (uint32_t*) param, 626 SKS_RSA_RMODQ_LENGTH(sks_key_p->key_length), 627 sksOffset + 628 SKS_RSA_RMODQ_OFFSET(sks_key_p->key_length), 629 FALSE); 630 DBG(("Return from write: %s\n", N8_Status_t_text(ret))); 631 CHECK_RETURN(ret); 632 633 /* Write the n value into the SKS. */ 634 DBG(("Writing n param into SKS.\n")); 635 636 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress + 637 PK_RSA_N_Param_Byte_Offset(&key); 638 639 ret = 640 n8_SKSWrite(targetSKS, 641 (uint32_t*) param, 642 SKS_RSA_N_LENGTH(sks_key_p->key_length), 643 sksOffset + 644 SKS_RSA_N_OFFSET(sks_key_p->key_length), 645 FALSE); 646 647 DBG(("Return from write: %s\n", N8_Status_t_text(ret))); 648 CHECK_RETURN(ret); 649 650 /* Write the pInv value into the SKS. */ 651 DBG(("Writing pInv param into SKS.\n")); 652 653 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress + 654 PK_RSA_U_Param_Byte_Offset(&key); 655 656 657 ret = 658 n8_SKSWrite(targetSKS, 659 (uint32_t*) param, 660 SKS_RSA_PINV_LENGTH(sks_key_p->key_length), 661 sksOffset + 662 SKS_RSA_PINV_OFFSET(sks_key_p->key_length), 663 FALSE); 664 665 DBG(("Return from write: %s\n", N8_Status_t_text(ret))); 666 CHECK_RETURN(ret); 667 668 /* Write the cp value into the SKS. */ 669 DBG(("Writing cp param into SKS.\n")); 670 671 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress + 672 PK_RSA_CP_Param_Byte_Offset(&key); 673 674 ret = n8_SKSWrite(targetSKS, 675 (uint32_t*) param, 676 SKS_RSA_CP_LENGTH(sks_key_p->key_length), 677 sksOffset + 678 SKS_RSA_CP_OFFSET(sks_key_p->key_length), 679 FALSE); 680 681 DBG(("Return from write: %s\n", N8_Status_t_text(ret))); 682 CHECK_RETURN(ret); 683 684 /* Write the cq value into the SKS. */ 685 DBG(("Writing cq param into SKS.\n")); 686 687 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress + 688 PK_RSA_CQ_Param_Byte_Offset(&key); 689 690 ret = 691 n8_SKSWrite(targetSKS, 692 (uint32_t*) param, 693 SKS_RSA_CQ_LENGTH(sks_key_p->key_length), 694 sksOffset + 695 SKS_RSA_CQ_OFFSET(sks_key_p->key_length), 696 FALSE); 697 DBG(("Return from write: %s\n", N8_Status_t_text(ret))); 698 } while (FALSE); 699 700 if (key.structureID == N8_RSA_STRUCT_ID) 701 { 702 N8_Status_t freeRet; 703 freeRet = N8_RSAFreeKey(&key); 704 /* if we terminated the processing loop with an error, let's report that 705 * error to the calling function rather than have it masked by the return 706 * from free key. */ 707 if (ret == N8_STATUS_OK) 708 { 709 ret = freeRet; 710 } 711 } 712 return ret; 713 714} /* N8_SKSAllocateRSA */ 715 716 717/***************************************************************************** 718 * N8_SKSAllocateDSA 719 *****************************************************************************/ 720/** @ingroup n8_sks 721 * @brief Allocate and write a private DSA key entry to an SKS PROM. 722 * 723 * Attempts to allocate, then write the key into an SKS PROM. 724 * 725 * @param keyMaterial_p RW: A N8_DSAKeyMaterial_t pointer. 726 * @param keyEntryName_p RW: A char pointer, the name of the sks entry. 727 * 728 * @par Externals: 729 * None 730 * 731 * @return 732 * N8_STATUS_OK indicates the key allocation and write successfully 733 * completed. 734 * N8_UNEXPECTED_ERROR indicates an error writing the key handle or that 735 * the API was not or could not be initialized. 736 * 737 * @par Assumptions: 738 * That the DSA key material pointer is valid. 739 *****************************************************************************/ 740N8_Status_t N8_SKSAllocateDSA(N8_DSAKeyMaterial_t *keyMaterial_p, 741 const N8_Buffer_t *keyEntryName_p) 742{ 743 N8_DSAKeyObject_t key; 744 N8_Buffer_t* param; 745 unsigned int keyLength; 746 uint32_t targetSKS = 0, sksOffset = 0; 747 N8_Status_t ret; 748 N8_SKSKeyHandle_t *sks_key_p; 749 750 do 751 { 752 ret = N8_preamble(); 753 CHECK_RETURN(ret); 754 CHECK_OBJECT(keyMaterial_p, ret); 755 CHECK_OBJECT(keyMaterial_p->privateKey.value_p, ret); 756 CHECK_OBJECT(keyEntryName_p, ret); 757 if (strlen(keyEntryName_p) >= N8_SKS_ENTRY_NAME_MAX_LENGTH) 758 { 759 ret = N8_INVALID_OBJECT; 760 break; 761 } 762 763 if ((keyMaterial_p->p.lengthBytes == 0) || 764 (keyMaterial_p->q.lengthBytes == 0)) 765 { 766 ret = N8_INVALID_KEY_SIZE; 767 break; 768 } 769 770 ret = n8_DSAValidateKey(keyMaterial_p, N8_PRIVATE); 771 CHECK_RETURN(ret); 772 773 sks_key_p = &keyMaterial_p->SKSKeyHandle; 774 775 ret = n8_verifyUnitID(keyMaterial_p->unitID, sks_key_p); 776 CHECK_RETURN(ret); 777 778 /* The key length field of the key handle is always in BNC digits. */ 779 sks_key_p->key_length = 780 BYTES_TO_PKDIGITS(keyMaterial_p->p.lengthBytes); 781 782 /* check to see if an entry of this name already exists and free 783 * it if so. */ 784 ret = n8_checkAndFreeEntry(keyEntryName_p, keyMaterial_p->SKSKeyHandle.unitID); 785 CHECK_RETURN(ret); 786 787 ret = N8_DSAInitializeKey(&key, N8_PRIVATE, keyMaterial_p, NULL); 788 CHECK_RETURN(ret); 789 790 keyLength = sks_key_p->key_length; 791 targetSKS = sks_key_p->unitID; 792 sks_key_p->key_type = N8_DSA_VERSION_1_KEY; 793 794 795 /* allocate an sks. */ 796 ret = n8_SKSAllocate(sks_key_p); 797 CHECK_RETURN(ret); 798 799 /* attempt to write the key information to the mapping files */ 800 strcpy(sks_key_p->entry_name, keyEntryName_p); 801 802 /* request N8 userspace daemon to write out a key handle file */ 803 ret = n8_daemon_sks_write(sks_key_p, keyEntryName_p); 804 if (ret != N8_STATUS_OK) 805 { 806 /* the write to the key handle failed. 807 * we need to unallocate the space 808 * and return a failure. */ 809 n8_SKSsetStatus(sks_key_p, SKS_FREE); 810 break; 811 } 812 813 sksOffset = sks_key_p->sks_offset; 814 815 /* Write the data into the SKS PROM. */ 816 DBG(("Writing key data into SKS.\n")); 817 818 /* The DSA parameter block to be stored the DSA has the following structure: 819 * p sks_offset key_length digits 820 * g*R mod p sks_offset + 4 * key_length key_length digits 821 * q sks_offset + 8 * key_length 2 digits 822 * x sks_offset + 8*kl + 8 2 digits 823 * p sks_offset + 8*kl + 16 1 digit 824 */ 825 826 /* Write the p value into the SKS. */ 827 DBG(("Writing p param into SKS.\n")); 828 829 param = key.paramBlock + PK_DSA_P_Param_Offset; 830 831 ret = 832 n8_SKSWrite(targetSKS, 833 (uint32_t*) param, 834 SKS_DSA_P_LENGTH(sks_key_p->key_length), 835 sksOffset + SKS_DSA_P_OFFSET(sks_key_p->key_length), 836 FALSE); 837 CHECK_RETURN(ret); 838 839 /* Write the gR mod p value into the SKS. */ 840 DBG(("Writing gR mod p param into SKS.\n")); 841 842 param = key.paramBlock + PK_DSA_GR_MOD_P_Param_Offset(sks_key_p->key_length); 843 844 ret = 845 n8_SKSWrite(targetSKS, 846 (uint32_t*) param, 847 SKS_DSA_GRMODP_LENGTH(sks_key_p->key_length), 848 sksOffset + SKS_DSA_GRMODP_OFFSET(sks_key_p->key_length), 849 FALSE); 850 CHECK_RETURN(ret); 851 852 /* Write the q value into the SKS. */ 853 DBG(("Writing q param into SKS.\n")); 854 855 param = key.paramBlock + 856 PK_DSA_Q_Param_Offset(sks_key_p->key_length); 857 858 ret = 859 n8_SKSWrite(targetSKS, 860 (uint32_t*) param, 861 SKS_DSA_Q_LENGTH(sks_key_p->key_length), 862 sksOffset + SKS_DSA_Q_OFFSET(sks_key_p->key_length), 863 FALSE); 864 CHECK_RETURN(ret); 865 866 /* Write the x value (private key) into the SKS. */ 867 DBG(("Writing x (private key) param into SKS.\n")); 868 869 param = key.paramBlock + 870 PK_DSA_X_Param_Offset(sks_key_p->key_length); 871 872 ret = 873 n8_SKSWrite(targetSKS, 874 (uint32_t*) param, 875 SKS_DSA_X_LENGTH(sks_key_p->key_length), 876 sksOffset + 877 SKS_DSA_X_OFFSET(sks_key_p->key_length), 878 FALSE); 879 CHECK_RETURN(ret); 880 881 /* Write the cp value into the SKS. */ 882 DBG(("Writing cp into SKS.\n")); 883 884 param = key.paramBlock + 885 PK_DSA_CP_Param_Offset(sks_key_p->key_length); 886 887 ret = 888 n8_SKSWrite(targetSKS, 889 (uint32_t*) param, 890 SKS_DSA_CP_LENGTH(sks_key_p->key_length), 891 sksOffset + SKS_DSA_CP_OFFSET(sks_key_p->key_length), 892 FALSE); 893 CHECK_RETURN(ret); 894 895 } while (FALSE); 896 897 if (key.structureID == N8_DSA_STRUCT_ID) 898 { 899 N8_Status_t freeRet; 900 freeRet = N8_DSAFreeKey(&key); 901 /* if we terminated the processing loop with an error, let's report that 902 * error to the calling function rather than have it masked by the return 903 * from free key. */ 904 if (ret == N8_STATUS_OK) 905 { 906 ret = freeRet; 907 } 908 } 909 910 return ret; 911 912} /* N8_SKSAllocateDSA */ 913 914/***************************************************************************** 915 * N8_SKSFree 916 *****************************************************************************/ 917/** @ingroup n8_sks 918 * @brief De-allocates and erases a private key entry to an SKS PROM. 919 * 920 * Attempts to de-allocate, then erase the key into an SKS PROM. 921 * 922 * @param keyHandle_p RW: A N8_SKSKeyHandle_t pointer. 923 * 924 * @par Externals: 925 * None 926 * 927 * @return 928 * N8_STATUS_OK indicates the key de-allocation and erase successfully 929 * completed. 930 * N8_UNEXPECTED_ERROR indicates an error erasing the SKS key entry or that 931 * the API was not or could not be initialized. 932 * 933 * @par Assumptions: 934 * That the key handle pointer is valid. 935 *****************************************************************************/ 936N8_Status_t N8_SKSFree(N8_SKSKeyHandle_t* keyHandle_p) 937{ 938 int words_to_free; 939 char* key_type; 940 int i; 941 uint32_t zero = 0x0; 942 N8_Status_t ret; 943 char fullFileName[1024]; 944 945 DBG(("SKS Free\n")); 946 947 ret = N8_preamble(); 948 if (ret != N8_STATUS_OK) 949 { 950 return ret; 951 } 952 if (keyHandle_p == NULL) 953 { 954 ret = N8_INVALID_KEY; 955 return ret; 956 } 957 958#ifdef N8DEBUG 959 n8_printSKSKeyHandle(keyHandle_p); 960#endif 961 962 if ((keyHandle_p->key_type) == N8_RSA_VERSION_1_KEY) 963 { 964 words_to_free = SKS_RSA_DATA_LENGTH(keyHandle_p->key_length); 965 key_type = "RSA"; 966 } 967 else if (keyHandle_p->key_type == N8_DSA_VERSION_1_KEY) 968 { 969 words_to_free = SKS_DSA_DATA_LENGTH(keyHandle_p->key_length); 970 key_type = "DSA"; 971 } 972 else 973 { 974 DBG(("Unknown key type.\n")); 975 return N8_INVALID_KEY; 976 } 977 978 DBG(("Zeroing out the key in the SKS PROM.\n")); 979 980 /* Grab the offset and begin deleting data! */ 981 for (i = keyHandle_p->sks_offset; 982 (i < keyHandle_p->sks_offset+words_to_free) && (i < SKS_PROM_MAX_OFFSET); 983 i++) 984 { 985 ret = n8_SKSWrite(keyHandle_p->unitID, &zero, 1, i, FALSE); 986 if (ret != N8_STATUS_OK) 987 { 988 DBG(("Error writing to SKS in N8_SKSFree. (%s)\n", 989 N8_Status_t_text(ret))); 990 return ret; 991 } 992 } 993 994 n8_SKSsetStatus(keyHandle_p, SKS_FREE); 995 996 sprintf(fullFileName, "%s%d/%s", 997 SKS_KEY_NODE_PATH, 998 keyHandle_p->unitID, 999 keyHandle_p->entry_name); 1000 1001 /* request N8 userspace daemon to delete the specfied file */ 1002 n8_daemon_sks_delete(fullFileName); 1003 1004 return N8_STATUS_OK; 1005 1006} /* N8_SKSFree */ 1007 1008 1009/***************************************************************************** 1010 * N8_SKSGetKeyHandle 1011 *****************************************************************************/ 1012/** @ingroup n8_sks 1013 * @brief Reads a key handle data from a named key entry for an SKS PROM. 1014 * 1015 * @param systemKeyNode RW: A char pointer, the named key entry. 1016 * @param keyHandle_p WO: A N8_SKSKeyHandle_t pointer. 1017 * 1018 * @par Externals: 1019 * SKS_initialized_g RW: A boolean value that indicates whether the SKS 1020 * admin interface API has been initialized. 1021 * @return 1022 * N8_STATUS_OK indicates the key read successfully completed. 1023 * N8_UNEXPECTED_ERROR indicates an error reading the SKS key entry or that 1024 * the API was not or could not be initialized. 1025 * 1026 *****************************************************************************/ 1027N8_Status_t N8_SKSGetKeyHandle(const N8_Buffer_t* keyEntryName, 1028 N8_SKSKeyHandle_t* keyHandle_p) 1029{ 1030 1031 N8_Status_t ret = N8_STATUS_OK; 1032 char fullFileName[1024]; 1033 int numberSKS; 1034 int i; 1035 int found; 1036 1037 DBG(("Get KeyHandle : \n")); 1038 1039 ret = N8_preamble(); 1040 if (ret != N8_STATUS_OK) 1041 { 1042 return ret; 1043 } 1044 1045 if ((keyEntryName == NULL) || (keyHandle_p == NULL)) 1046 { 1047 return N8_INVALID_OBJECT; 1048 } 1049 1050 /* get the number of units */ 1051 numberSKS = n8_getNumUnits(); 1052 1053 /* check to see if we can have a buffer overrun. the +4 is for the trailing 1054 * '/' and for the size of the unitID -- assuming the number of units is no 1055 * more than 999. */ 1056 1057 if ((strlen(SKS_KEY_NODE_PATH) + strlen(keyEntryName) + 4) >= 1058 sizeof(fullFileName)) 1059 { 1060 return N8_UNEXPECTED_ERROR; 1061 } 1062 found = -1; 1063 for (i = 0; i < numberSKS; i++) 1064 { 1065 sprintf(fullFileName, "%s%d/%s", SKS_KEY_NODE_PATH, i, keyEntryName); 1066 /* request N8 userspace daemon to read from the specfied key 1067 * handle file 1068 */ 1069 ret = n8_daemon_sks_read(keyHandle_p, fullFileName); 1070 if (ret == N8_STATUS_OK) 1071 { 1072 found = i; 1073 /* n8_daemon_sks_read does not set the entry name */ 1074 strcpy(keyHandle_p->entry_name, keyEntryName); 1075#if N8_SKS_ROUND_ROBIN 1076 keyHandle_p->unitID = N8_ANY_UNIT; 1077#endif /* N8_SKS_ROUND_ROBIN */ 1078 break; 1079 } 1080 } 1081 if (found == -1) 1082 { 1083 ret = N8_INVALID_KEY; 1084 } 1085 1086 return ret; 1087} /* N8_SKSGetKeyHandle */ 1088 1089/***************************************************************************** 1090 * N8_SKSReset 1091 *****************************************************************************/ 1092/** @ingroup n8_sks 1093 * @brief Obliterates all data within an SKS PROM. 1094 * 1095 * Attempts to de-allocate, then erase the all key entries in an SKS PROM. 1096 * THIS SHOULD NEVER BE INVOKED EXCEPT TO CLEAR ALL KEYS IN A GIVEN PROM. 1097 * THIS IS AN IRREVERSIBLE ACTION. 1098 * 1099 * @param targetSKS RW: A int, the target SKS PROM. 1100 * 1101 * @par Externals: 1102 * None 1103 * 1104 * @return 1105 * N8_STATUS_OK indicates the key de-allocation and erase successfully 1106 * completed. 1107 * N8_UNEXPECTED_ERROR indicates an error erasing the SKS key entry or that 1108 * the API was not or could not be initialized. 1109 * 1110 *****************************************************************************/ 1111N8_Status_t N8_SKSReset(N8_Unit_t targetSKS) 1112{ 1113 int i; 1114 N8_Status_t ret = N8_STATUS_OK; 1115 N8_Unit_t firstSKS, lastSKS; 1116 int numberSKS; 1117 1118 DBG(("N8_SKSReset: entering...\n")); 1119 1120 ret = N8_preamble(); 1121 if (ret != N8_STATUS_OK) 1122 { 1123 return ret; 1124 } 1125 1126 /* get the number of units */ 1127 numberSKS = n8_getNumUnits(); 1128 1129 if (targetSKS == N8_ANY_UNIT) 1130 { 1131 firstSKS = 0; 1132 lastSKS = numberSKS-1; 1133 } 1134 else if (targetSKS >= 0 && 1135 targetSKS < numberSKS) 1136 { 1137 firstSKS = lastSKS = targetSKS; 1138 } 1139 else 1140 { 1141 ret = N8_INVALID_VALUE; 1142 return ret; 1143 } 1144 /* loop over the SKS units to be reset. it will either be all or just the 1145 * targetSKS. */ 1146 for (i = firstSKS; i <= lastSKS; i++) 1147 { 1148 1149 ret = n8_SKSResetUnit(i); 1150 if (ret != N8_STATUS_OK) 1151 { 1152 return ret; 1153 } 1154 /* request N8 userspace daemon to remove 1155 * all the key handle files on the host 1156 * file system that are under the specified 1157 * execution unit 1158 */ 1159 ret = n8_daemon_sks_reset(i); 1160 if (ret != N8_STATUS_OK) 1161 { 1162 DBG(("Error resetting SKS files: %d\n", ret)); 1163 return N8_FILE_ERROR; 1164 } 1165 } 1166 DBG(("N8_SKSReset: leaving...\n")); 1167 1168 1169 return ret; 1170} /* N8_SKSReset */ 1171 1172/***************************************************************************** 1173 * N8_SKSVerifyRSA 1174 *****************************************************************************/ 1175N8_Status_t N8_SKSVerifyRSA(N8_SKSKeyHandle_t* keyHandle_p, 1176 N8_Buffer_t* input_p, 1177 N8_Buffer_t* result_p) 1178{ 1179 N8_RSAKeyObject_t privateKey; 1180 N8_Buffer_t* decryptBuffer_p; 1181 N8_Status_t ret; 1182 1183 DBG(("Verify RSA Key.\n")); 1184 1185 ret = N8_preamble(); 1186 if (ret != N8_STATUS_OK) 1187 { 1188 return ret; 1189 } 1190 /* Set the material to NULL as we are using the SKS. */ 1191 ret = N8_RSAInitializeKey(&privateKey, N8_PRIVATE_SKS, NULL, NULL); 1192 if (ret != N8_STATUS_OK) 1193 { 1194 DBG(("Could not initialize RSA private key from SKS. (%s)\n", 1195 N8_Status_t_text(ret))); 1196 return ret; 1197 } 1198 1199 decryptBuffer_p = (N8_Buffer_t *) N8_UMALLOC(privateKey.privateKeyLength); 1200 if (decryptBuffer_p == NULL) 1201 { 1202 DBG(("Could not allocate %i bytes for decrypt buffer.\n", 1203 privateKey.privateKeyLength)); 1204 return N8_MALLOC_FAILED; 1205 } 1206 1207 ret = N8_RSADecrypt(&privateKey, input_p, 1208 privateKey.privateKeyLength, 1209 decryptBuffer_p, NULL); 1210 if (ret != N8_STATUS_OK) 1211 { 1212 DBG(("Could not complete RSA decrypt using SKS private key. (%s)\n", 1213 N8_Status_t_text(ret))); 1214 return ret; 1215 } 1216 1217 /* Compare the buffers. If they are different, then indicate this in the return code. */ 1218 if (memcmp(result_p, decryptBuffer_p, privateKey.privateKeyLength) != 0) 1219 { 1220 DBG(("Message buffers are not the same. " 1221 "RSA Decrypt failed or SKS private key material is not valid.\n")); 1222 return N8_VERIFICATION_FAILED; 1223 } 1224 1225 DBG(("RSA Decrypt good: SKS private key is valid.\n")); 1226 1227 return N8_STATUS_OK; 1228} /* N8_SKSVerifyRSA */ 1229 1230/***************************************************************************** 1231 * N8_SKSVerifyDSA 1232 *****************************************************************************/ 1233 1234N8_Status_t N8_SKSVerifyDSA(N8_SKSKeyHandle_t* keyHandle_p, 1235 N8_Buffer_t* inputHash_p, 1236 N8_Buffer_t* resultRValue_p, 1237 N8_Buffer_t* resultSValue_p) 1238{ 1239 N8_DSAKeyObject_t privateKey; 1240 N8_Buffer_t* signRValueBuffer_p, *signSValueBuffer_p; 1241 N8_Status_t ret; 1242 DBG(("Verify DSA Key.\n")); 1243 1244 ret = N8_preamble(); 1245 if (ret != N8_STATUS_OK) 1246 { 1247 return ret; 1248 } 1249 1250 /* Set the material to NULL as we are using the SKS. */ 1251 ret = N8_DSAInitializeKey(&privateKey, N8_PRIVATE_SKS, NULL, NULL); 1252 if (ret != N8_STATUS_OK) 1253 { 1254 DBG(("Could not initialize DSA private key from SKS. (%s)\n", 1255 N8_Status_t_text(ret))); 1256 return ret; 1257 } 1258 1259 /* !!!!!! Is there a #define for the S and R value byte lengths?!?!?!! */ 1260 if ((signRValueBuffer_p = (N8_Buffer_t *) N8_UMALLOC(20)) != 0) 1261 { 1262 DBG(("Could not allocate %i bytes for DSA sign R value buffer.\n", 1263 privateKey.modulusLength)); 1264 return N8_MALLOC_FAILED; 1265 } 1266 1267 if ((signSValueBuffer_p = (N8_Buffer_t *) N8_UMALLOC(20)) != 0) 1268 { 1269 DBG(("Could not allocate %i bytes for DSA sign S value buffer.\n", 1270 privateKey.modulusLength)); 1271 return N8_MALLOC_FAILED; 1272 } 1273 1274 ret = N8_DSASign(&privateKey, inputHash_p, signRValueBuffer_p, 1275 signSValueBuffer_p, NULL); 1276 if (ret != N8_STATUS_OK) 1277 { 1278 DBG(("Could not complete DSA sign using SKS private key. (%s)\n", 1279 N8_Status_t_text(ret))); 1280 return ret; 1281 } 1282 1283 /* Compare the buffers. If they are different, then indicate this in the return code. */ 1284 if (memcmp(resultRValue_p, signRValueBuffer_p, 20) != 0) 1285 { 1286 DBG(("Result R value buffers are not the same. " 1287 "DSA Sign failed or SKS private key material is not valid.\n")); 1288 return N8_VERIFICATION_FAILED; 1289 } 1290 1291 if (memcmp(resultSValue_p, signSValueBuffer_p, 20) != 0) 1292 { 1293 DBG(("Result S value buffers are not the same. " 1294 "DSA Sign failed or SKS private key material is not valid.\n")); 1295 return N8_VERIFICATION_FAILED; 1296 } 1297 1298 DBG(("DSA Sign good: SKS private key is valid.\n")); 1299 1300 return N8_STATUS_OK; 1301 1302} /* N8_SKSVerifyDSA */ 1303 1304 1305