1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2012 Milan Jurik. All rights reserved.
  25  */
  26 
  27 #include <stdlib.h>
  28 #include <string.h>
  29 #include <strings.h>
  30 #include <lber.h>
  31 #include <security/cryptoki.h>
  32 #include "softDSA.h"
  33 #include "softDH.h"
  34 #include "softRSA.h"
  35 #include "softObject.h"
  36 #include "softASN1.h"
  37 
  38 #define OID_TAG                 0x06
  39 
  40 #define MAX_DH_KEY      MAX_DH_KEYLENGTH_IN_BYTES       /* bytes in DH key */
  41 static uchar_t  DH_OID[] = {
  42         /* DH key agreement OID:  1 . 2 . 840 . 113549 . 1 . 3 . 1 */
  43         0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x03, 0x01
  44 };
  45 
  46 #define MAX_DH942_KEY   MAX_DH_KEYLENGTH_IN_BYTES /* bytes in DH X9.42 key */
  47 static uchar_t  DH942_OID[] = {
  48         /* DH X9.42 OID:  1 . 2 . 840 . 10046 . 1  */
  49         0x2A, 0x86, 0x48, 0xCE, 0x3E, 0x01
  50 };
  51 
  52 #define MAX_DSA_KEY     MAX_DSA_KEY_LEN         /* bytes in DSA key */
  53 static uchar_t  DSA_OID[] = {
  54         /* DSA algorithm OID:  1 . 2 . 840 . 10040 . 4 . 1  */
  55         0x2A, 0x86, 0x48, 0xCE, 0x38, 0x04, 0x01
  56 };
  57 
  58 #define MAX_RSA_KEY     MAX_RSA_KEYLENGTH_IN_BYTES      /* bytes in RSA key */
  59 static uchar_t  RSA_OID[] = {
  60         /* RSA algorithm OID:  1 . 2 . 840 . 113549 . 1 . 1 . 1 */
  61         0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01
  62 };
  63 
  64 
  65 /*
  66  * If the first bit of big integer is non-zero (i.e, first byte is
  67  * 0x80 or greater), it may be interpreted as an ASN.1 negative number.
  68  * Add one leading byte of zero-padding only in these cases to ensure
  69  * it is treated as an unsigned integer.
  70  */
  71 static CK_RV
  72 pad_bigint_attr(biginteger_t *src, biginteger_t *dst)
  73 {
  74         int     padding;
  75 
  76         /* Src and dst must already by previously allocated. */
  77         if (src == NULL || dst == NULL)
  78                 return (CKR_HOST_MEMORY);
  79 
  80         if (src->big_value_len == 0) {
  81                 dst->big_value = NULL;
  82                 dst->big_value_len = 0;
  83                 return (CKR_OK);
  84         }
  85         /*
  86          * Realloc() may free() or shrink previous memory location, so
  87          * clear out potentially sensitive data before that happens.
  88          */
  89         if (dst->big_value != NULL)
  90                 (void) memset(dst->big_value, 0x0, dst->big_value_len);
  91 
  92         padding = (src->big_value[0] < 0x80) ? 0 : 1;
  93         dst->big_value_len = src->big_value_len + padding;
  94 
  95         dst->big_value = realloc(dst->big_value, dst->big_value_len);
  96         if (dst->big_value == NULL)
  97                 return (CKR_HOST_MEMORY);
  98 
  99         /* Set zero-pad at first byte, then append actual big_value. */
 100         dst->big_value[0] = 0x0;
 101         (void) memcpy(&(dst->big_value[padding]), src->big_value,
 102             src->big_value_len);
 103         return (CKR_OK);
 104 }
 105 
 106 /*
 107  * Sometimes there is one bytes of zero-padding, if a big integer may
 108  * be interpreted as an ASN.1 negative number (i.e, the first bit is
 109  * non-zero, the first byte is 0x80 or greater).  Remove first byte
 110  * of zero-padding in those cases from the decoded octet strings.
 111  */
 112 static CK_RV
 113 unpad_bigint_attr(biginteger_t src, biginteger_t *dst)
 114 {
 115         int     offset;
 116 
 117         if (dst == NULL)
 118                 return (CKR_HOST_MEMORY);
 119 
 120         if (src.big_value_len == 0) {
 121                 dst->big_value = NULL;
 122                 dst->big_value_len = 0;
 123                 return (CKR_OK);
 124         }
 125 
 126         offset = (src.big_value[0] == 0x00) ? 1 : 0;
 127         dst->big_value_len = src.big_value_len - offset;
 128 
 129         /*
 130          * Must allocate memory here because subsequent calls to
 131          * copy_bigint_attr() just redirect pointer; it doesn't
 132          * really copy the bigint like the function name implies.
 133          */
 134         dst->big_value = malloc(dst->big_value_len);
 135         if (dst->big_value == NULL)
 136                 return (CKR_HOST_MEMORY);
 137 
 138         (void) memcpy(dst->big_value, &(src.big_value[offset]),
 139             dst->big_value_len);
 140         return (CKR_OK);
 141 }
 142 
 143 
 144 /* Encode RSA private key in ASN.1 BER syntax. */
 145 static CK_RV
 146 rsa_pri_to_asn1(soft_object_t *objp, uchar_t *buf, ulong_t *buf_len)
 147 {
 148         CK_RV           rv = CKR_OK;
 149         BerElement      *key_asn = NULLBER, *p8obj_asn = NULLBER;
 150         BerValue        *key_octs = NULL, *p8obj_octs = NULL;
 151         int             version = SOFT_ASN_VERSION;
 152         biginteger_t    tmp_pad = { NULL, 0 };
 153 
 154         /*
 155          * The ASN.1 syntax for an RSA private key is:
 156          *
 157          * PKCS#8       \* PrivateKeyInfo *\
 158          * ---------------------------------
 159          * Sequence {
 160          *      version         INTEGER;
 161          *      Sequence {      \* PrivateKeyAlgorithm *\
 162          *              OID     0x06,   \* RSA algorithm OID *\
 163          *              param(NULL)
 164          *      }
 165          *      RSAPrivateKey   OCTETSTRING =
 166          *              PKCS#1  \* RSAPrivateKey *\
 167          *              ---------------------------
 168          *              Sequence {
 169          *                      version         INTEGER,
 170          *                      modulus         INTEGER,
 171          *                      publicExponent  INTEGER,
 172          *                      privateExponent INTEGER,
 173          *                      prime1          INTEGER,
 174          *                      prime2          INTEGER,
 175          *                      exponent1       INTEGER,
 176          *                      exponent2       INTEGER,
 177          *                      coefficient     INTEGER
 178          *              }
 179          * }
 180          *
 181          * The code below starts building the innermost octets
 182          * RSAPrivateKey, and then builds the PrivateKeyInfo
 183          * sequence around that octet string.  The BER syntax
 184          * used in this function is (others may be possible):
 185          *      { i { to n } { i to  to  to  to  to  to  to  to } }
 186          * where "i" is for integers with fixed size
 187          * where "to" is for integers that vary in size (length + value)
 188          * where "n" is for nulls
 189          * where "{}" delimit sequences
 190          */
 191 
 192         /* RSAPrivateKey ... */
 193         if ((key_asn = ber_alloc()) == NULLBER)
 194                 return (CKR_HOST_MEMORY);
 195 
 196         /* ... begin-sequence { version, */
 197         if (ber_printf(key_asn, "{i", version) == -1) {
 198                 rv = CKR_GENERAL_ERROR;
 199                 goto cleanup_rsapri2asn;
 200         }
 201 
 202         /* ... modulus, */
 203         if ((rv = pad_bigint_attr(OBJ_PRI_RSA_MOD(objp), &tmp_pad)) != CKR_OK)
 204                 goto cleanup_rsapri2asn;
 205         if (ber_printf(key_asn, "to", LBER_INTEGER,
 206             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 207                 rv = CKR_GENERAL_ERROR;
 208                 goto cleanup_rsapri2asn;
 209         }
 210 
 211         /* ... public exponent, */
 212         if ((rv = pad_bigint_attr(OBJ_PRI_RSA_PUBEXPO(objp), &tmp_pad)) !=
 213             CKR_OK)
 214                 goto cleanup_rsapri2asn;
 215 
 216         else if (ber_printf(key_asn, "to", LBER_INTEGER, tmp_pad.big_value,
 217             tmp_pad.big_value_len) == -1) {
 218                 rv = CKR_GENERAL_ERROR;
 219                 goto cleanup_rsapri2asn;
 220         }
 221 
 222         /* ... private exponent, */
 223         if ((rv = pad_bigint_attr(OBJ_PRI_RSA_PRIEXPO(objp), &tmp_pad)) !=
 224             CKR_OK)
 225                 goto cleanup_rsapri2asn;
 226         if (ber_printf(key_asn, "to", LBER_INTEGER,
 227             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 228                 rv = CKR_GENERAL_ERROR;
 229                 goto cleanup_rsapri2asn;
 230         }
 231 
 232         /* ... prime 1, */
 233         if ((rv = pad_bigint_attr(OBJ_PRI_RSA_PRIME1(objp), &tmp_pad)) !=
 234             CKR_OK)
 235                 goto cleanup_rsapri2asn;
 236         else if (ber_printf(key_asn, "to", LBER_INTEGER,
 237             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 238                 rv = CKR_GENERAL_ERROR;
 239                 goto cleanup_rsapri2asn;
 240         }
 241 
 242         /* ... prime 2, */
 243         if ((rv = pad_bigint_attr(OBJ_PRI_RSA_PRIME2(objp), &tmp_pad)) !=
 244             CKR_OK)
 245                 goto cleanup_rsapri2asn;
 246         else if (ber_printf(key_asn, "to", LBER_INTEGER,
 247             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 248                 rv = CKR_GENERAL_ERROR;
 249                 goto cleanup_rsapri2asn;
 250         }
 251 
 252         /* ... exponent 1, */
 253         if ((rv = pad_bigint_attr(OBJ_PRI_RSA_EXPO1(objp), &tmp_pad)) != CKR_OK)
 254                 goto cleanup_rsapri2asn;
 255         else if (ber_printf(key_asn, "to", LBER_INTEGER,
 256             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 257                 rv = CKR_GENERAL_ERROR;
 258                 goto cleanup_rsapri2asn;
 259         }
 260 
 261         /* ... exponent 2, */
 262         if ((rv = pad_bigint_attr(OBJ_PRI_RSA_EXPO2(objp), &tmp_pad)) != CKR_OK)
 263                 goto cleanup_rsapri2asn;
 264         else if (ber_printf(key_asn, "to", LBER_INTEGER,
 265             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 266                 rv = CKR_GENERAL_ERROR;
 267                 goto cleanup_rsapri2asn;
 268         }
 269 
 270         /* ... coefficient } end-sequence */
 271         if ((rv = pad_bigint_attr(OBJ_PRI_RSA_COEF(objp), &tmp_pad)) != CKR_OK)
 272                 goto cleanup_rsapri2asn;
 273         else if (ber_printf(key_asn, "to}", LBER_INTEGER,
 274             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 275                 rv = CKR_GENERAL_ERROR;
 276                 goto cleanup_rsapri2asn;
 277         }
 278 
 279         /* Convert key ASN.1 to octet string. */
 280         if (ber_flatten(key_asn, &key_octs) == -1) {
 281                 rv = CKR_GENERAL_ERROR;
 282                 goto cleanup_rsapri2asn;
 283         }
 284 
 285         /* PKCS#8 PrivateKeyInfo ... */
 286         if ((p8obj_asn = ber_alloc()) == NULLBER) {
 287                 rv = CKR_HOST_MEMORY;
 288                 goto cleanup_rsapri2asn;
 289         }
 290 
 291         /*
 292          * Embed key octet string into PKCS#8 object ASN.1:
 293          * begin-sequence {
 294          *      version
 295          *      begin-sequence {
 296          *              OID,
 297          *              NULL
 298          *      } end-sequence
 299          *      RSAPrivateKey
 300          * } end-sequence
 301          */
 302         if (ber_printf(p8obj_asn, "{i{ton}o}", version,
 303             OID_TAG, RSA_OID, sizeof (RSA_OID), /* NULL parameter, */
 304             key_octs->bv_val, key_octs->bv_len) == -1) {
 305                 rv = CKR_GENERAL_ERROR;
 306                 goto cleanup_rsapri2asn;
 307         }
 308 
 309         /* Convert PKCS#8 object ASN.1 to octet string. */
 310         if (ber_flatten(p8obj_asn, &p8obj_octs) == -1) {
 311                 rv = CKR_GENERAL_ERROR;
 312                 goto cleanup_rsapri2asn;
 313         }
 314 
 315         /* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
 316         /*
 317          * If the user passes in a null buf, then buf_len is set.
 318          * If the user passes in a value with buf_len, then it can
 319          * be checked to see if the accompanying buf is big enough.
 320          * If it is, the octet string is copied into a pre-malloc'd
 321          * buf; otherwise the user must resize buf and call again.
 322          * In either case, buf_len is reset to the corrected size.
 323          * See PKCS#11 section 11.2.
 324          */
 325 #ifdef _LP64
 326         /* LINTED E_CAST_INT_TO_SMALL_INT */
 327         if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
 328 #else
 329         if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
 330 #endif
 331                 *buf_len = p8obj_octs->bv_len;
 332                 rv = (buf == NULL) ? CKR_OK : CKR_BUFFER_TOO_SMALL;
 333                 goto cleanup_rsapri2asn;
 334         }
 335 
 336         *buf_len = p8obj_octs->bv_len;
 337         (void) memcpy(buf, p8obj_octs->bv_val, *buf_len);
 338 
 339 cleanup_rsapri2asn:
 340 
 341         if (tmp_pad.big_value != NULL) {
 342                 (void) memset(tmp_pad.big_value, 0x0, tmp_pad.big_value_len);
 343                 free(tmp_pad.big_value);
 344         }
 345 
 346         if (key_asn != NULLBER)
 347                 ber_free(key_asn, 1);
 348 
 349         if (key_octs != NULL)
 350                 ber_bvfree(key_octs);
 351 
 352         if (p8obj_asn != NULLBER)
 353                 ber_free(p8obj_asn, 1);
 354 
 355         if (p8obj_octs != NULL)
 356                 ber_bvfree(p8obj_octs);
 357 
 358         return (rv);
 359 }
 360 
 361 /* Encode DSA private key in ASN.1 BER syntax. */
 362 static CK_RV
 363 dsa_pri_to_asn1(soft_object_t *objp, uchar_t *buf, ulong_t *buf_len)
 364 {
 365         CK_RV           rv = CKR_OK;
 366         BerElement      *key_asn = NULLBER, *p8obj_asn = NULLBER;
 367         BerValue        *key_octs = NULL, *p8obj_octs = NULL;
 368         int             version = SOFT_ASN_VERSION;
 369         biginteger_t    tmp_pad = { NULL, 0 };
 370 
 371         /*
 372          * The ASN.1 syntax for a DSA private key is:
 373          *
 374          * PKCS#8       \* PrivateKeyInfo *\
 375          * ---------------------------------
 376          * Sequence {
 377          *      version         INTEGER;
 378          *      Sequence {      \* PrivateKeyAlgorithm *\
 379          *              OID     0x06,   \* DSA algorithm OID *\
 380          *              param(DSS-params)       OCTETSTRING =
 381          *                      PKCS#?  \* DSSParameter *\
 382          *                      ----------------------------------
 383          *                      Sequence {
 384          *                              prime   INTEGER,
 385          *                              subprime INTEGER,
 386          *                              base    INTEGER,
 387          *              }
 388          *      }
 389          *      DSAPrivateKey   OCTETSTRING =
 390          *              PKCS#1  \* DSAPrivateKey *\
 391          *              ---------------------------
 392          *              value           INTEGER
 393          * }
 394          *
 395          * The code below starts building the innermost octets
 396          * DSAPrivateKey, and then builds the PrivateKeyInfo
 397          * sequence around that octet string.  The BER syntax
 398          * used in this function is (others may be possible):
 399          *      { i { to { to to to } } to }
 400          * where "i" is for integers with fixed size
 401          * where "to" is for integers that vary in size (length + value)
 402          * where "{}" delimit sequences
 403          */
 404 
 405         /* DSAPrivateKey ... */
 406         if ((key_asn = ber_alloc()) == NULLBER)
 407                 return (CKR_HOST_MEMORY);
 408 
 409         /* ... value */
 410         if ((rv = pad_bigint_attr(OBJ_PRI_DSA_VALUE(objp), &tmp_pad)) != CKR_OK)
 411                 goto cleanup_dsapri2asn;
 412         if (ber_printf(key_asn, "to", LBER_INTEGER,
 413             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 414                 rv = CKR_GENERAL_ERROR;
 415                 goto cleanup_dsapri2asn;
 416         }
 417 
 418         /* Convert key ASN.1 to octet string. */
 419         if (ber_flatten(key_asn, &key_octs) == -1) {
 420                 rv = CKR_GENERAL_ERROR;
 421                 goto cleanup_dsapri2asn;
 422         }
 423 
 424         /* PKCS#8 PrivateKeyInfo ... */
 425         if ((p8obj_asn = ber_alloc()) == NULLBER) {
 426                 rv = CKR_HOST_MEMORY;
 427                 goto cleanup_dsapri2asn;
 428         }
 429 
 430         /*
 431          * Start off the PKCS#8 object ASN.1:
 432          * begin-sequence {
 433          *      version
 434          *      begin-sequence {
 435          *              OID,
 436          * ...
 437          */
 438         if (ber_printf(p8obj_asn, "{i{to", version,
 439             OID_TAG, DSA_OID, sizeof (DSA_OID)) == -1) {
 440                 rv = CKR_GENERAL_ERROR;
 441                 goto cleanup_dsapri2asn;
 442         }
 443 
 444         /*
 445          * Add DSS parameters:
 446          * ...
 447          *              begin-sequence {
 448          *                      prime,
 449          * ...
 450          */
 451         if ((rv = pad_bigint_attr(OBJ_PRI_DSA_PRIME(objp), &tmp_pad)) != CKR_OK)
 452                 goto cleanup_dsapri2asn;
 453         if (ber_printf(p8obj_asn, "{to", LBER_INTEGER,
 454             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 455                 rv = CKR_GENERAL_ERROR;
 456                 goto cleanup_dsapri2asn;
 457         }
 458 
 459         /*
 460          * ...
 461          *                      subprime,
 462          * ...
 463          */
 464         if ((rv = pad_bigint_attr(OBJ_PRI_DSA_SUBPRIME(objp), &tmp_pad)) !=
 465             CKR_OK)
 466                 goto cleanup_dsapri2asn;
 467         if (ber_printf(p8obj_asn, "to", LBER_INTEGER,
 468             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 469                 rv = CKR_GENERAL_ERROR;
 470                 goto cleanup_dsapri2asn;
 471         }
 472 
 473         /*
 474          * ...
 475          *                      base
 476          *              } end-sequence
 477          */
 478         if ((rv = pad_bigint_attr(OBJ_PRI_DSA_BASE(objp), &tmp_pad)) != CKR_OK)
 479                 goto cleanup_dsapri2asn;
 480         if (ber_printf(p8obj_asn, "to}", LBER_INTEGER,
 481             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 482                 rv = CKR_GENERAL_ERROR;
 483                 goto cleanup_dsapri2asn;
 484         }
 485 
 486         /*
 487          * Add the key octet string:
 488          *      } end-sequence
 489          *      DSAPrivateKey
 490          * } end-sequence
 491          */
 492         if (ber_printf(p8obj_asn, "}o}",
 493             key_octs->bv_val, key_octs->bv_len) == -1) {
 494                 rv = CKR_GENERAL_ERROR;
 495                 goto cleanup_dsapri2asn;
 496         }
 497 
 498         /* Convert PKCS#8 object ASN.1 to octet string. */
 499         if (ber_flatten(p8obj_asn, &p8obj_octs) == -1) {
 500                 rv = CKR_GENERAL_ERROR;
 501                 goto cleanup_dsapri2asn;
 502         }
 503 
 504         /* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
 505         /*
 506          * If the user passes in a null buf, then buf_len is set.
 507          * If the user passes in a value with buf_len, then it can
 508          * be checked to see if the accompanying buf is big enough.
 509          * If it is, the octet string is copied into a pre-malloc'd
 510          * buf; otherwise the user must resize buf and call again.
 511          * In either case, buf_len is reset to the corrected size.
 512          * See PKCS#11 section 11.2.
 513          */
 514 #ifdef _LP64
 515         /* LINTED E_CAST_INT_TO_SMALL_INT */
 516         if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
 517 #else
 518         if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
 519 #endif
 520                 *buf_len = p8obj_octs->bv_len;
 521                 rv = (buf == NULL) ? CKR_OK : CKR_BUFFER_TOO_SMALL;
 522                 goto cleanup_dsapri2asn;
 523         }
 524 
 525         *buf_len = p8obj_octs->bv_len;
 526         (void) memcpy(buf, p8obj_octs->bv_val, *buf_len);
 527 
 528 cleanup_dsapri2asn:
 529 
 530         if (tmp_pad.big_value != NULL) {
 531                 (void) memset(tmp_pad.big_value, 0x0, tmp_pad.big_value_len);
 532                 free(tmp_pad.big_value);
 533         }
 534 
 535         if (key_asn != NULLBER)
 536                 ber_free(key_asn, 1);
 537 
 538         if (key_octs != NULL)
 539                 ber_bvfree(key_octs);
 540 
 541         if (p8obj_asn != NULLBER)
 542                 ber_free(p8obj_asn, 1);
 543 
 544         if (p8obj_octs != NULL)
 545                 ber_bvfree(p8obj_octs);
 546 
 547         return (rv);
 548 }
 549 
 550 /* Encode DH private key in ASN.1 BER syntax. */
 551 static CK_RV
 552 dh_pri_to_asn1(soft_object_t *objp, uchar_t *buf, ulong_t *buf_len)
 553 {
 554         CK_RV           rv = CKR_OK;
 555         BerElement      *key_asn = NULLBER, *p8obj_asn = NULLBER;
 556         BerValue        *key_octs = NULL, *p8obj_octs = NULL;
 557         int             version = SOFT_ASN_VERSION;
 558         biginteger_t    tmp_pad = { NULL, 0 };
 559 
 560         /*
 561          * The ASN.1 syntax for a DH private key is:
 562          *
 563          * PKCS#8       \* PrivateKeyInfo *\
 564          * ---------------------------------
 565          * Sequence {
 566          *      version         INTEGER;
 567          *      Sequence {      \* PrivateKeyAlgorithm *\
 568          *              OID     0x06,   \* DH algorithm OID *\
 569          *              param(DH-params) OCTETSTRING =
 570          *                      PKCS#3  \* DHParameter *\
 571          *                      -------------------------
 572          *                      Sequence {
 573          *                              prime   INTEGER,
 574          *                              base    INTEGER
 575          *                      }
 576          *      }
 577          *      DHPrivateKey    OCTETSTRING =
 578          *              PKCS#1  \* DHPrivateKey *\
 579          *              --------------------------
 580          *              value           INTEGER
 581          * }
 582          *
 583          * The code below starts building the innermost octets
 584          * DHPrivateKey, and then builds the PrivateKeyInfo
 585          * sequence around that octet string.  The BER syntax
 586          * used in this function is (others may be possible):
 587          *      { i { to { to to } } to }
 588          * where "i" is for integers with fixed size
 589          * where "to" is for integers that vary in size (length + value)
 590          * where "{}" delimit sequences
 591          */
 592 
 593         /* DHPrivateKey ... */
 594         if ((key_asn = ber_alloc()) == NULLBER)
 595                 return (CKR_HOST_MEMORY);
 596 
 597         /* ... value */
 598         if ((rv = pad_bigint_attr(OBJ_PRI_DH_VALUE(objp), &tmp_pad)) != CKR_OK)
 599                 goto cleanup_dhpri2asn;
 600         if (ber_printf(key_asn, "to", LBER_INTEGER,
 601             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 602                 rv = CKR_GENERAL_ERROR;
 603                 goto cleanup_dhpri2asn;
 604         }
 605 
 606         /* Convert key ASN.1 to octet string. */
 607         if (ber_flatten(key_asn, &key_octs) == -1) {
 608                 rv = CKR_GENERAL_ERROR;
 609                 goto cleanup_dhpri2asn;
 610         }
 611 
 612         /* PKCS#8 PrivateKeyInfo ... */
 613         if ((p8obj_asn = ber_alloc()) == NULLBER) {
 614                 rv = CKR_HOST_MEMORY;
 615                 goto cleanup_dhpri2asn;
 616         }
 617 
 618         /*
 619          * Start off the PKCS#8 object ASN.1:
 620          * begin-sequence {
 621          *      version
 622          *      begin-sequence {
 623          *              OID,
 624          * ...
 625          */
 626         if (ber_printf(p8obj_asn, "{i{to", version,
 627             OID_TAG, DH_OID, sizeof (DH_OID)) == -1) {
 628                 rv = CKR_GENERAL_ERROR;
 629                 goto cleanup_dhpri2asn;
 630         }
 631 
 632         /*
 633          * Add DH parameters:
 634          * ...
 635          *              begin-sequence {
 636          *                      prime,
 637          * ...
 638          */
 639         if ((rv = pad_bigint_attr(OBJ_PRI_DH_PRIME(objp), &tmp_pad)) != CKR_OK)
 640                 goto cleanup_dhpri2asn;
 641         if (ber_printf(p8obj_asn, "{to", LBER_INTEGER,
 642             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 643                 rv = CKR_GENERAL_ERROR;
 644                 goto cleanup_dhpri2asn;
 645         }
 646 
 647         /*
 648          * ...
 649          *                      base
 650          *              } end-sequence
 651          */
 652         if ((rv = pad_bigint_attr(OBJ_PRI_DH_BASE(objp), &tmp_pad)) != CKR_OK)
 653                 goto cleanup_dhpri2asn;
 654         if (ber_printf(p8obj_asn, "to}", LBER_INTEGER,
 655             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 656                 rv = CKR_GENERAL_ERROR;
 657                 goto cleanup_dhpri2asn;
 658         }
 659 
 660         /*
 661          * Add the key octet string:
 662          *      } end-sequence
 663          *      DSAPrivateKey
 664          * } end-sequence
 665          */
 666         if (ber_printf(p8obj_asn, "}o}",
 667             key_octs->bv_val, key_octs->bv_len) == -1) {
 668                 rv = CKR_GENERAL_ERROR;
 669                 goto cleanup_dhpri2asn;
 670         }
 671 
 672         /* Convert PKCS#8 object ASN.1 to octet string. */
 673         if (ber_flatten(p8obj_asn, &p8obj_octs) == -1) {
 674                 rv = CKR_GENERAL_ERROR;
 675                 goto cleanup_dhpri2asn;
 676         }
 677 
 678         /* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
 679         /*
 680          * If the user passes in a null buf, then buf_len is set.
 681          * If the user passes in a value with buf_len, then it can
 682          * be checked to see if the accompanying buf is big enough.
 683          * If it is, the octet string is copied into a pre-malloc'd
 684          * buf; otherwise the user must resize buf and call again.
 685          * In either case, buf_len is reset to the corrected size.
 686          * See PKCS#11 section 11.2.
 687          */
 688 #ifdef _LP64
 689         /* LINTED E_CAST_INT_TO_SMALL_INT */
 690         if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
 691 #else
 692         if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
 693 #endif
 694                 *buf_len = p8obj_octs->bv_len;
 695                 rv = (buf == NULL) ? CKR_OK : CKR_BUFFER_TOO_SMALL;
 696                 goto cleanup_dhpri2asn;
 697         }
 698 
 699         *buf_len = p8obj_octs->bv_len;
 700         (void) memcpy(buf, p8obj_octs->bv_val, *buf_len);
 701 
 702 cleanup_dhpri2asn:
 703 
 704         if (tmp_pad.big_value != NULL) {
 705                 (void) memset(tmp_pad.big_value, 0x0, tmp_pad.big_value_len);
 706                 free(tmp_pad.big_value);
 707         }
 708 
 709         if (key_asn != NULLBER)
 710                 ber_free(key_asn, 1);
 711 
 712         if (key_octs != NULL)
 713                 ber_bvfree(key_octs);
 714 
 715         if (p8obj_asn != NULLBER)
 716                 ber_free(p8obj_asn, 1);
 717 
 718         if (p8obj_octs != NULL)
 719                 ber_bvfree(p8obj_octs);
 720 
 721         return (rv);
 722 }
 723 
 724 /* Encode DH X9.42 private key in ASN.1 BER syntax. */
 725 static CK_RV
 726 x942_dh_pri_to_asn1(soft_object_t *objp, uchar_t *buf, ulong_t *buf_len)
 727 {
 728         CK_RV           rv = CKR_OK;
 729         BerElement      *key_asn = NULLBER, *p8obj_asn = NULLBER;
 730         BerValue        *key_octs = NULL, *p8obj_octs = NULL;
 731         int             version = SOFT_ASN_VERSION;
 732         biginteger_t    tmp_pad = { NULL, 0 };
 733 
 734         /*
 735          * The ASN.1 syntax for a X9.42 DH private key is:
 736          *
 737          * PKCS#8       \* PrivateKeyInfo *\
 738          * ---------------------------------
 739          * Sequence {
 740          *      version         INTEGER;
 741          *      Sequence {      \* PrivateKeyAlgorithm *\
 742          *              OID     0x06,   \* DH X9.42 algorithm OID *\
 743          *              param(DH-params) OCTETSTRING =
 744          *                      PKCS#3  \* DHParameter *\
 745          *                      -------------------------
 746          *                      Sequence {
 747          *                              prime   INTEGER,
 748          *                              base    INTEGER,
 749          *                              subprime INTEGER \* for X9.42 *\
 750          *                      }
 751          *      }
 752          *      DHPrivateKey    OCTETSTRING =
 753          *              PKCS#1  \* DHPrivateKey *\
 754          *              --------------------------
 755          *              value           INTEGER
 756          * }
 757          *
 758          * The code below starts building the innermost octets
 759          * DHPrivateKey, and then builds the PrivateKeyInfo
 760          * sequence around that octet string.  The BER syntax
 761          * used in this function is (others may be possible):
 762          *      { i { to { to to } } to }
 763          * where "i" is for integers with fixed size
 764          * where "to" is for integers that vary in size (length + value)
 765          * where "{}" delimit sequences
 766          */
 767 
 768         /* DHPrivateKey ... */
 769         if ((key_asn = ber_alloc()) == NULLBER)
 770                 return (CKR_HOST_MEMORY);
 771 
 772         /* ... value */
 773         if ((rv = pad_bigint_attr(OBJ_PRI_DH942_VALUE(objp), &tmp_pad)) !=
 774             CKR_OK)
 775                 goto cleanup_x942dhpri2asn;
 776         if (ber_printf(key_asn, "to", LBER_INTEGER,
 777             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 778                 rv = CKR_GENERAL_ERROR;
 779                 goto cleanup_x942dhpri2asn;
 780         }
 781 
 782         /* Convert key ASN.1 to octet string. */
 783         if (ber_flatten(key_asn, &key_octs) == -1) {
 784                 rv = CKR_GENERAL_ERROR;
 785                 goto cleanup_x942dhpri2asn;
 786         }
 787 
 788         /* PKCS#8 PrivateKeyInfo ... */
 789         if ((p8obj_asn = ber_alloc()) == NULLBER) {
 790                 rv = CKR_HOST_MEMORY;
 791                 goto cleanup_x942dhpri2asn;
 792         }
 793 
 794         /*
 795          * Start off the PKCS#8 object ASN.1:
 796          * begin-sequence {
 797          *      version
 798          *      begin-sequence {
 799          *              OID,
 800          * ...
 801          */
 802         if (ber_printf(p8obj_asn, "{i{to", version,
 803             OID_TAG, DH942_OID, sizeof (DH942_OID)) == -1) {
 804                 rv = CKR_GENERAL_ERROR;
 805                 goto cleanup_x942dhpri2asn;
 806         }
 807 
 808         /*
 809          * Add DH parameters:
 810          * ...
 811          *              begin-sequence {
 812          *                      prime,
 813          * ...
 814          */
 815         if ((rv = pad_bigint_attr(OBJ_PRI_DH942_PRIME(objp), &tmp_pad)) !=
 816             CKR_OK)
 817                 goto cleanup_x942dhpri2asn;
 818         if (ber_printf(p8obj_asn, "{to", LBER_INTEGER,
 819             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 820                 rv = CKR_GENERAL_ERROR;
 821                 goto cleanup_x942dhpri2asn;
 822         }
 823 
 824         /*
 825          * ...
 826          *                      base,
 827          * ...
 828          */
 829         if ((rv = pad_bigint_attr(OBJ_PRI_DH942_BASE(objp), &tmp_pad)) !=
 830             CKR_OK)
 831                 goto cleanup_x942dhpri2asn;
 832         if (ber_printf(p8obj_asn, "to", LBER_INTEGER,
 833             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 834                 rv = CKR_GENERAL_ERROR;
 835                 goto cleanup_x942dhpri2asn;
 836         }
 837 
 838         /*
 839          * ...
 840          *                      subprime
 841          *              } end-sequence
 842          */
 843         if ((rv = pad_bigint_attr(OBJ_PRI_DH942_SUBPRIME(objp), &tmp_pad)) !=
 844             CKR_OK)
 845                 goto cleanup_x942dhpri2asn;
 846         if (ber_printf(p8obj_asn, "to}", LBER_INTEGER,
 847             tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
 848                 rv = CKR_GENERAL_ERROR;
 849                 goto cleanup_x942dhpri2asn;
 850         }
 851 
 852         /*
 853          * Add the key octet string:
 854          *      } end-sequence
 855          *      DHPrivateKey
 856          * } end-sequence
 857          */
 858         if (ber_printf(p8obj_asn, "}o}",
 859             key_octs->bv_val, key_octs->bv_len) == -1) {
 860                 rv = CKR_GENERAL_ERROR;
 861                 goto cleanup_x942dhpri2asn;
 862         }
 863 
 864         /* Convert PKCS#8 object ASN.1 to octet string. */
 865         if (ber_flatten(p8obj_asn, &p8obj_octs) == -1) {
 866                 rv = CKR_GENERAL_ERROR;
 867                 goto cleanup_x942dhpri2asn;
 868         }
 869 
 870         /* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
 871         /*
 872          * If the user passes in a null buf, then buf_len is set.
 873          * If the user passes in a value with buf_len, then it can
 874          * be checked to see if the accompanying buf is big enough.
 875          * If it is, the octet string is copied into a pre-malloc'd
 876          * buf; otherwise the user must resize buf and call again.
 877          * In either case, buf_len is reset to the corrected size.
 878          * See PKCS#11 section 11.2.
 879          */
 880 #ifdef _LP64
 881         /* LINTED E_CAST_INT_TO_SMALL_INT */
 882         if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
 883 #else
 884         if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
 885 #endif
 886                 *buf_len = p8obj_octs->bv_len;
 887                 rv = (buf == NULL) ? CKR_OK : CKR_BUFFER_TOO_SMALL;
 888                 goto cleanup_x942dhpri2asn;
 889         }
 890 
 891         *buf_len = p8obj_octs->bv_len;
 892         (void) memcpy(buf, p8obj_octs->bv_val, *buf_len);
 893 
 894 cleanup_x942dhpri2asn:
 895 
 896         if (tmp_pad.big_value != NULL) {
 897                 (void) memset(tmp_pad.big_value, 0x0, tmp_pad.big_value_len);
 898                 free(tmp_pad.big_value);
 899         }
 900 
 901         if (key_asn != NULLBER)
 902                 ber_free(key_asn, 1);
 903 
 904         if (key_octs != NULL)
 905                 ber_bvfree(key_octs);
 906 
 907         if (p8obj_asn != NULLBER)
 908                 ber_free(p8obj_asn, 1);
 909 
 910         if (p8obj_octs != NULL)
 911                 ber_bvfree(p8obj_octs);
 912 
 913         return (rv);
 914 }
 915 
 916 /*
 917  * Encode the object key from the soft_object_t into ASN.1 format.
 918  */
 919 CK_RV
 920 soft_object_to_asn1(soft_object_t *objp, uchar_t *buf, ulong_t *buf_len)
 921 {
 922         CK_OBJECT_CLASS class = objp->class;
 923         CK_KEY_TYPE     keytype = objp->key_type;
 924 
 925         switch (class) {
 926 
 927         case CKO_PRIVATE_KEY:
 928                 switch (keytype) {
 929                 case CKK_RSA:
 930                         return (rsa_pri_to_asn1(objp, buf, buf_len));
 931 
 932                 case CKK_DSA:
 933                         return (dsa_pri_to_asn1(objp, buf, buf_len));
 934 
 935                 case CKK_DH:
 936                         return (dh_pri_to_asn1(objp, buf, buf_len));
 937 
 938                 case CKK_X9_42_DH:
 939                         return (x942_dh_pri_to_asn1(objp, buf, buf_len));
 940 
 941                 default:
 942                         return (CKR_FUNCTION_NOT_SUPPORTED);
 943                 } /* keytype */
 944 
 945         default:
 946                 return (CKR_FUNCTION_NOT_SUPPORTED);
 947 
 948         } /* class */
 949 }
 950 
 951 /* Decode ASN.1 BER syntax into RSA private key. */
 952 static CK_RV
 953 asn1_to_rsa_pri(private_key_obj_t *keyp, uchar_t *buf, ulong_t buf_len)
 954 {
 955         CK_RV           rv = CKR_OK;
 956         BerValue        p8obj_octs, key_octs;
 957         BerElement      *p8obj_asn = NULLBER, *key_asn = NULLBER;
 958         ber_len_t       size, tmplen;
 959         char            *cookie;
 960         int             version;
 961         uchar_t         oid[sizeof (RSA_OID) + 1];
 962         biginteger_t    tmp, tmp_nopad = { NULL, 0 };
 963 
 964         p8obj_octs.bv_val = (char *)buf;
 965 #ifdef _LP64
 966         /* LINTED E_CAST_INT_TO_SMALL_INT */
 967         p8obj_octs.bv_len = (ber_len_t)buf_len;
 968 #else
 969         p8obj_octs.bv_len = (ber_len_t)buf_len;
 970 #endif
 971 
 972         key_octs.bv_val = NULL;
 973         key_octs.bv_len = 0;
 974 
 975         /* Decode PKCS#8 object ASN.1, verifying it is RSA private key. */
 976         if ((p8obj_asn = ber_init(&p8obj_octs)) == NULLBER)
 977                 return (CKR_GENERAL_ERROR);
 978 
 979         /* PKCS#8 PrivateKeyInfo ... */
 980         if (ber_first_element(p8obj_asn, &size, &cookie) != LBER_INTEGER) {
 981                 rv = CKR_WRAPPED_KEY_INVALID;
 982                 goto cleanup_asn2rsapri;
 983         }
 984         /* ... begin-sequence { version, */
 985         (void) ber_scanf(p8obj_asn, "i", &version); /* "{i" ? */
 986 
 987         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
 988                 rv = CKR_WRAPPED_KEY_INVALID;
 989                 goto cleanup_asn2rsapri;
 990         }
 991         /* ... begin-sequence { */
 992         (void) ber_scanf(p8obj_asn, "{");
 993 
 994         if (ber_next_element(p8obj_asn, &size, cookie) != OID_TAG) {
 995                 rv = CKR_WRAPPED_KEY_INVALID;
 996                 goto cleanup_asn2rsapri;
 997         }
 998         /* ... OID, \* RSA algorithm OID *\ */
 999         if (size != sizeof (RSA_OID)) {
1000                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1001                 goto cleanup_asn2rsapri;
1002         }
1003         size = sizeof (oid);
1004         (void) ber_scanf(p8obj_asn, "s", oid, &size);
1005         if (memcmp(oid, RSA_OID, size) != 0) {
1006                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1007                 goto cleanup_asn2rsapri;
1008         }
1009 
1010         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_NULL) {
1011                 rv = CKR_WRAPPED_KEY_INVALID;
1012                 goto cleanup_asn2rsapri;
1013         }
1014         /* ... param(NULL) } end-sequence */
1015         (void) ber_scanf(p8obj_asn, "n");               /* "n}" ? */
1016 
1017         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_OCTETSTRING) {
1018                 rv = CKR_WRAPPED_KEY_INVALID;
1019                 goto cleanup_asn2rsapri;
1020         }
1021         /* ... RSAPrivateKey } end-sequence */
1022         key_octs.bv_len = size + 1;
1023         if ((key_octs.bv_val = malloc(size + 1)) == NULL) {
1024                 rv = CKR_HOST_MEMORY;
1025                 goto cleanup_asn2rsapri;
1026         }
1027         (void) ber_scanf(p8obj_asn, "s",                /* "s}" ? */
1028             key_octs.bv_val, &key_octs.bv_len);
1029 
1030         /* Decode key octet string into softtoken key object. */
1031         if ((key_asn = ber_init(&key_octs)) == NULLBER) {
1032                 rv = CKR_GENERAL_ERROR;
1033                 goto cleanup_asn2rsapri;
1034         }
1035 
1036         /* ... begin-sequence { version, */
1037         if (ber_first_element(key_asn, &size, &cookie) != LBER_INTEGER) {
1038                 rv = CKR_WRAPPED_KEY_INVALID;
1039                 goto cleanup_asn2rsapri;
1040         }
1041         (void) ber_scanf(key_asn, "i", &version);   /* "{i" ? */
1042 
1043         /* ... modulus, */
1044         if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1045                 rv = CKR_WRAPPED_KEY_INVALID;
1046                 goto cleanup_asn2rsapri;
1047         }
1048         if (size > MAX_RSA_KEY) {
1049                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1050                 goto cleanup_asn2rsapri;
1051         }
1052         tmplen = size + 1;
1053         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1054                 rv = CKR_HOST_MEMORY;
1055                 goto cleanup_asn2rsapri;
1056         }
1057         (void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
1058         tmp.big_value_len = tmplen;
1059         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1060                 free(tmp.big_value);
1061                 goto cleanup_asn2rsapri;
1062         }
1063         free(tmp.big_value);
1064         copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_MOD(keyp));
1065 
1066         /* ... public exponent, */
1067         if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1068                 rv = CKR_WRAPPED_KEY_INVALID;
1069                 goto error_asn2rsapri;
1070         }
1071         if (size > MAX_RSA_KEY) {
1072                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1073                 goto error_asn2rsapri;
1074         }
1075         tmplen = size + 1;
1076         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1077                 rv = CKR_HOST_MEMORY;
1078                 goto error_asn2rsapri;
1079         }
1080         (void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
1081         tmp.big_value_len = tmplen;
1082         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1083                 free(tmp.big_value);
1084                 goto error_asn2rsapri;
1085         }
1086         free(tmp.big_value);
1087         copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_PUBEXPO(keyp));
1088 
1089         /* ... private exponent, */
1090         if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1091                 rv = CKR_WRAPPED_KEY_INVALID;
1092                 goto error_asn2rsapri;
1093         }
1094         if (size > MAX_RSA_KEY) {
1095                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1096                 goto error_asn2rsapri;
1097         }
1098         tmplen = size + 1;
1099         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1100                 rv = CKR_HOST_MEMORY;
1101                 goto error_asn2rsapri;
1102         }
1103         (void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
1104         tmp.big_value_len = tmplen;
1105         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1106                 free(tmp.big_value);
1107                 goto error_asn2rsapri;
1108         }
1109         free(tmp.big_value);
1110         copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_PRIEXPO(keyp));
1111 
1112         /* ... prime 1, */
1113         if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1114                 rv = CKR_WRAPPED_KEY_INVALID;
1115                 goto error_asn2rsapri;
1116         }
1117         if (size > MAX_RSA_KEY) {
1118                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1119                 goto error_asn2rsapri;
1120         }
1121         tmplen = size + 1;
1122         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1123                 rv = CKR_HOST_MEMORY;
1124                 goto error_asn2rsapri;
1125         }
1126         (void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
1127         tmp.big_value_len = tmplen;
1128         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1129                 free(tmp.big_value);
1130                 goto error_asn2rsapri;
1131         }
1132         free(tmp.big_value);
1133         copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_PRIME1(keyp));
1134 
1135         /* ... prime 2, */
1136         if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1137                 rv = CKR_WRAPPED_KEY_INVALID;
1138                 goto error_asn2rsapri;
1139         }
1140         if (size > MAX_RSA_KEY) {
1141                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1142                 goto error_asn2rsapri;
1143         }
1144         tmplen = size + 1;
1145         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1146                 rv = CKR_HOST_MEMORY;
1147                 goto error_asn2rsapri;
1148         }
1149         (void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
1150         tmp.big_value_len = tmplen;
1151         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1152                 free(tmp.big_value);
1153                 goto error_asn2rsapri;
1154         }
1155         free(tmp.big_value);
1156         copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_PRIME2(keyp));
1157 
1158         /* ... exponent 1, */
1159         if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1160                 rv = CKR_WRAPPED_KEY_INVALID;
1161                 goto error_asn2rsapri;
1162         }
1163         if (size > MAX_RSA_KEY) {
1164                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1165                 goto error_asn2rsapri;
1166         }
1167         tmplen = size + 1;
1168         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1169                 rv = CKR_HOST_MEMORY;
1170                 goto error_asn2rsapri;
1171         }
1172         (void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
1173         tmp.big_value_len = tmplen;
1174         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1175                 free(tmp.big_value);
1176                 goto error_asn2rsapri;
1177         }
1178         free(tmp.big_value);
1179         copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_EXPO1(keyp));
1180 
1181         /* ... exponent 2, */
1182         if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1183                 rv = CKR_WRAPPED_KEY_INVALID;
1184                 goto error_asn2rsapri;
1185         }
1186         if (size > MAX_RSA_KEY) {
1187                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1188                 goto error_asn2rsapri;
1189         }
1190         tmplen = size + 1;
1191         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1192                 rv = CKR_HOST_MEMORY;
1193                 goto error_asn2rsapri;
1194         }
1195         (void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
1196         tmp.big_value_len = tmplen;
1197         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1198                 free(tmp.big_value);
1199                 goto error_asn2rsapri;
1200         }
1201         free(tmp.big_value);
1202         copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_EXPO2(keyp));
1203 
1204         /* ... coefficient } end-sequence */
1205         if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1206                 rv = CKR_WRAPPED_KEY_INVALID;
1207                 goto error_asn2rsapri;
1208         }
1209         if (size > MAX_RSA_KEY) {
1210                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1211                 goto error_asn2rsapri;
1212         }
1213         tmplen = size + 1;
1214         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1215                 rv = CKR_HOST_MEMORY;
1216                 goto error_asn2rsapri;
1217         }
1218         (void) ber_scanf(key_asn, "s",          /* "s}" ? */
1219             tmp.big_value, &tmplen);
1220         tmp.big_value_len = tmplen;
1221         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1222                 free(tmp.big_value);
1223                 goto error_asn2rsapri;
1224         }
1225         free(tmp.big_value);
1226         copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_COEF(keyp));
1227 
1228         goto cleanup_asn2rsapri;
1229 
1230 error_asn2rsapri:
1231 
1232         bigint_attr_cleanup(KEY_PRI_RSA_MOD(keyp));
1233         bigint_attr_cleanup(KEY_PRI_RSA_PUBEXPO(keyp));
1234         bigint_attr_cleanup(KEY_PRI_RSA_PRIEXPO(keyp));
1235         bigint_attr_cleanup(KEY_PRI_RSA_PRIME1(keyp));
1236         bigint_attr_cleanup(KEY_PRI_RSA_PRIME2(keyp));
1237         bigint_attr_cleanup(KEY_PRI_RSA_EXPO1(keyp));
1238         bigint_attr_cleanup(KEY_PRI_RSA_EXPO2(keyp));
1239         bigint_attr_cleanup(KEY_PRI_RSA_COEF(keyp));
1240 
1241 cleanup_asn2rsapri:
1242 
1243         if (tmp_nopad.big_value != NULL) {
1244                 (void) memset(tmp_nopad.big_value, 0x0,
1245                     tmp_nopad.big_value_len);
1246                 free(tmp_nopad.big_value);
1247         }
1248 
1249         if (p8obj_asn != NULLBER)
1250                 ber_free(p8obj_asn, 1);
1251 
1252         if (key_octs.bv_val != NULL)
1253                 free(key_octs.bv_val);
1254 
1255         if (key_asn != NULLBER)
1256                 ber_free(key_asn, 1);
1257 
1258         return (rv);
1259 }
1260 
1261 /* Decode ASN.1 BER syntax into DSA private key. */
1262 static CK_RV
1263 asn1_to_dsa_pri(private_key_obj_t *keyp, uchar_t *buf, ulong_t buf_len)
1264 {
1265         CK_RV           rv = CKR_OK;
1266         BerValue        p8obj_octs, key_octs;
1267         BerElement      *p8obj_asn = NULLBER, *key_asn = NULLBER;
1268         ber_len_t       size, tmplen;
1269         char            *cookie;
1270         int             version;
1271         uchar_t         oid[sizeof (DSA_OID) + 1];
1272         biginteger_t    tmp, tmp_nopad = { NULL, 0 };
1273 
1274         p8obj_octs.bv_val = (char *)buf;
1275 #ifdef _LP64
1276         /* LINTED E_CAST_INT_TO_SMALL_INT */
1277         p8obj_octs.bv_len = (ber_len_t)buf_len;
1278 #else
1279         p8obj_octs.bv_len = (ber_len_t)buf_len;
1280 #endif
1281 
1282         key_octs.bv_val = NULL;
1283         key_octs.bv_len = 0;
1284 
1285         /* Decode PKCS#8 object ASN.1, verifying it is DSA private key. */
1286         if ((p8obj_asn = ber_init(&p8obj_octs)) == NULLBER)
1287                 return (CKR_GENERAL_ERROR);
1288 
1289         /* PKCS#8 PrivateKeyInfo ... */
1290         if (ber_first_element(p8obj_asn, &size, &cookie) != LBER_INTEGER) {
1291                 rv = CKR_WRAPPED_KEY_INVALID;
1292                 goto cleanup_asn2dsapri;
1293         }
1294         /* ... begin-sequence { version, */
1295         (void) ber_scanf(p8obj_asn, "i", &version); /* "{i" ? */
1296 
1297         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
1298                 rv = CKR_WRAPPED_KEY_INVALID;
1299                 goto cleanup_asn2dsapri;
1300         }
1301         /* ... begin-sequence { */
1302         (void) ber_scanf(p8obj_asn, "{");
1303 
1304         if (ber_next_element(p8obj_asn, &size, cookie) != OID_TAG) {
1305                 rv = CKR_WRAPPED_KEY_INVALID;
1306                 goto cleanup_asn2dsapri;
1307         }
1308         /* ... OID, \* DSA algorithm OID *\ */
1309         if (size != sizeof (DSA_OID)) {
1310                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1311                 goto cleanup_asn2dsapri;
1312         }
1313         size = sizeof (oid);
1314         (void) ber_scanf(p8obj_asn, "s", oid, &size);
1315         if (memcmp(oid, DSA_OID, size) != 0) {
1316                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1317                 goto cleanup_asn2dsapri;
1318         }
1319 
1320         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
1321                 rv = CKR_WRAPPED_KEY_INVALID;
1322                 goto cleanup_asn2dsapri;
1323         }
1324         /* ... begin-sequence { */
1325         (void) ber_scanf(p8obj_asn, "{");
1326 
1327         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1328                 rv = CKR_WRAPPED_KEY_INVALID;
1329                 goto cleanup_asn2dsapri;
1330         }
1331         /* ... prime, */
1332         if (size > MAX_DSA_KEY) {
1333                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1334                 goto cleanup_asn2dsapri;
1335         }
1336         tmplen = size + 1;
1337         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1338                 rv = CKR_HOST_MEMORY;
1339                 goto cleanup_asn2dsapri;
1340         }
1341         (void) ber_scanf(p8obj_asn, "s", tmp.big_value, &tmplen);
1342         tmp.big_value_len = tmplen;
1343         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1344                 free(tmp.big_value);
1345                 goto cleanup_asn2dsapri;
1346         }
1347         free(tmp.big_value);
1348         copy_bigint_attr(&tmp_nopad, KEY_PRI_DSA_PRIME(keyp));
1349 
1350         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1351                 rv = CKR_WRAPPED_KEY_INVALID;
1352                 goto error_asn2dsapri;
1353         }
1354         /* ... subprime, */
1355         if (size > MAX_DSA_KEY) {
1356                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1357                 goto error_asn2dsapri;
1358         }
1359         tmplen = size + 1;
1360         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1361                 rv = CKR_HOST_MEMORY;
1362                 goto error_asn2dsapri;
1363         }
1364         (void) ber_scanf(p8obj_asn, "s", tmp.big_value, &tmplen);
1365         tmp.big_value_len = tmplen;
1366         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1367                 free(tmp.big_value);
1368                 goto error_asn2dsapri;
1369         }
1370         free(tmp.big_value);
1371         copy_bigint_attr(&tmp_nopad, KEY_PRI_DSA_SUBPRIME(keyp));
1372 
1373         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1374                 rv = CKR_WRAPPED_KEY_INVALID;
1375                 goto error_asn2dsapri;
1376         }
1377         /* ... base } end-sequence } end-sequence */
1378         if (size > MAX_DSA_KEY) {
1379                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1380                 goto error_asn2dsapri;
1381         }
1382         tmplen = size + 1;
1383         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1384                 rv = CKR_HOST_MEMORY;
1385                 goto error_asn2dsapri;
1386         }
1387         (void) ber_scanf(p8obj_asn, "s",                /* "s}}" ? */
1388             tmp.big_value, &tmplen);
1389         tmp.big_value_len = tmplen;
1390         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1391                 free(tmp.big_value);
1392                 goto error_asn2dsapri;
1393         }
1394         free(tmp.big_value);
1395         copy_bigint_attr(&tmp_nopad, KEY_PRI_DSA_BASE(keyp));
1396 
1397         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_OCTETSTRING) {
1398                 rv = CKR_WRAPPED_KEY_INVALID;
1399                 goto error_asn2dsapri;
1400         }
1401         /* ... DSAPrivateKey } end-sequence */
1402         key_octs.bv_len = size + 1;
1403         if ((key_octs.bv_val = malloc(size + 1)) == NULL) {
1404                 rv = CKR_HOST_MEMORY;
1405                 goto error_asn2dsapri;
1406         }
1407         (void) ber_scanf(p8obj_asn, "s",                /* "s}" ? */
1408             key_octs.bv_val, &key_octs.bv_len);
1409 
1410         /* Decode key octet string into softtoken key object. */
1411         if ((key_asn = ber_init(&key_octs)) == NULLBER) {
1412                 rv = CKR_GENERAL_ERROR;
1413                 goto error_asn2dsapri;
1414         }
1415 
1416         if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1417                 rv = CKR_WRAPPED_KEY_INVALID;
1418                 goto error_asn2dsapri;
1419         }
1420         /* ... value } end-sequence */
1421         if (size > MAX_DSA_KEY) {
1422                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1423                 goto error_asn2dsapri;
1424         }
1425         tmplen = size + 1;
1426         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1427                 rv = CKR_HOST_MEMORY;
1428                 goto error_asn2dsapri;
1429         }
1430         (void) ber_scanf(key_asn, "s",          /* "s}" ? */
1431             tmp.big_value, &tmplen);
1432         tmp.big_value_len = tmplen;
1433         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1434                 free(tmp.big_value);
1435                 goto error_asn2dsapri;
1436         }
1437         free(tmp.big_value);
1438         copy_bigint_attr(&tmp_nopad, KEY_PRI_DSA_VALUE(keyp));
1439 
1440         goto cleanup_asn2dsapri;
1441 
1442 error_asn2dsapri:
1443 
1444         bigint_attr_cleanup(KEY_PRI_DSA_PRIME(keyp));
1445         bigint_attr_cleanup(KEY_PRI_DSA_SUBPRIME(keyp));
1446         bigint_attr_cleanup(KEY_PRI_DSA_BASE(keyp));
1447         bigint_attr_cleanup(KEY_PRI_DSA_VALUE(keyp));
1448 
1449 cleanup_asn2dsapri:
1450 
1451         if (tmp_nopad.big_value != NULL) {
1452                 (void) memset(tmp_nopad.big_value, 0x0,
1453                     tmp_nopad.big_value_len);
1454                 free(tmp_nopad.big_value);
1455         }
1456 
1457         if (p8obj_asn != NULLBER)
1458                 ber_free(p8obj_asn, 1);
1459 
1460         if (key_octs.bv_val != NULL)
1461                 free(key_octs.bv_val);
1462 
1463         if (key_asn != NULLBER)
1464                 ber_free(key_asn, 1);
1465 
1466         return (rv);
1467 }
1468 
1469 /* Decode ASN.1 BER syntax into DH private key. */
1470 static CK_RV
1471 asn1_to_dh_pri(private_key_obj_t *keyp, uchar_t *buf, ulong_t buf_len)
1472 {
1473         CK_RV           rv = CKR_OK;
1474         BerValue        p8obj_octs, key_octs;
1475         BerElement      *p8obj_asn = NULLBER, *key_asn = NULLBER;
1476         ber_len_t       size, tmplen;
1477         char            *cookie;
1478         int             version;
1479         uchar_t         oid[sizeof (DH_OID) + 1];
1480         biginteger_t    tmp, tmp_nopad = { NULL, 0 };
1481 
1482         p8obj_octs.bv_val = (char *)buf;
1483 #ifdef _LP64
1484         /* LINTED E_CAST_INT_TO_SMALL_INT */
1485         p8obj_octs.bv_len = (ber_len_t)buf_len;
1486 #else
1487         p8obj_octs.bv_len = (ber_len_t)buf_len;
1488 #endif
1489 
1490         key_octs.bv_val = NULL;
1491         key_octs.bv_len = 0;
1492 
1493         /* Decode PKCS#8 object ASN.1, verifying it is DH private key. */
1494         if ((p8obj_asn = ber_init(&p8obj_octs)) == NULLBER)
1495                 return (CKR_GENERAL_ERROR);
1496 
1497         /* PKCS#8 PrivateKeyInfo ... */
1498         if (ber_first_element(p8obj_asn, &size, &cookie) != LBER_INTEGER) {
1499                 rv = CKR_WRAPPED_KEY_INVALID;
1500                 goto cleanup_asn2dhpri;
1501         }
1502         /* ... begin-sequence { version, */
1503         (void) ber_scanf(p8obj_asn, "i", &version); /* "{i" ? */
1504 
1505         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
1506                 rv = CKR_WRAPPED_KEY_INVALID;
1507                 goto cleanup_asn2dhpri;
1508         }
1509         /* ... begin-sequence { */
1510         (void) ber_scanf(p8obj_asn, "{");
1511 
1512         if (ber_next_element(p8obj_asn, &size, cookie) != OID_TAG) {
1513                 rv = CKR_WRAPPED_KEY_INVALID;
1514                 goto cleanup_asn2dhpri;
1515         }
1516         /* ... OID, \* DH algorithm OID *\ */
1517         if (size != sizeof (DH_OID)) {
1518                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1519                 goto cleanup_asn2dhpri;
1520         }
1521         size = sizeof (oid);
1522         (void) ber_scanf(p8obj_asn, "s", oid, &size);
1523         if (memcmp(oid, DH_OID, size) != 0) {
1524                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1525                 goto cleanup_asn2dhpri;
1526         }
1527 
1528         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
1529                 rv = CKR_WRAPPED_KEY_INVALID;
1530                 goto cleanup_asn2dhpri;
1531         }
1532         /* ... begin-sequence { */
1533         (void) ber_scanf(p8obj_asn, "{");
1534 
1535         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1536                 rv = CKR_WRAPPED_KEY_INVALID;
1537                 goto cleanup_asn2dhpri;
1538         }
1539         /* ... prime, */
1540         if (size > MAX_DH_KEY) {
1541                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1542                 goto cleanup_asn2dhpri;
1543         }
1544         tmplen = size + 1;
1545         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1546                 rv = CKR_HOST_MEMORY;
1547                 goto cleanup_asn2dhpri;
1548         }
1549         (void) ber_scanf(p8obj_asn, "s", tmp.big_value, &tmplen);
1550         tmp.big_value_len = tmplen;
1551         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1552                 free(tmp.big_value);
1553                 goto cleanup_asn2dhpri;
1554         }
1555         free(tmp.big_value);
1556         copy_bigint_attr(&tmp_nopad, KEY_PRI_DH_PRIME(keyp));
1557 
1558         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1559                 rv = CKR_WRAPPED_KEY_INVALID;
1560                 goto error_asn2dhpri;
1561         }
1562         /* ... base } end-sequence } end-sequence */
1563         if (size > MAX_DH_KEY) {
1564                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1565                 goto error_asn2dhpri;
1566         }
1567         tmplen = size + 1;
1568         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1569                 rv = CKR_HOST_MEMORY;
1570                 goto error_asn2dhpri;
1571         }
1572         (void) ber_scanf(p8obj_asn, "s",                /* "s}}" ? */
1573             tmp.big_value, &tmplen);
1574         tmp.big_value_len = tmplen;
1575         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1576                 free(tmp.big_value);
1577                 goto error_asn2dhpri;
1578         }
1579         free(tmp.big_value);
1580         copy_bigint_attr(&tmp_nopad, KEY_PRI_DH_BASE(keyp));
1581 
1582         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_OCTETSTRING) {
1583                 rv = CKR_WRAPPED_KEY_INVALID;
1584                 goto error_asn2dhpri;
1585         }
1586         /* ... DHPrivateKey } end-sequence */
1587         key_octs.bv_len = size + 1;
1588         if ((key_octs.bv_val = malloc(size + 1)) == NULL) {
1589                 rv = CKR_HOST_MEMORY;
1590                 goto error_asn2dhpri;
1591         }
1592         (void) ber_scanf(p8obj_asn, "s",                /* "s}" ? */
1593             key_octs.bv_val, &key_octs.bv_len);
1594 
1595         /* Decode key octet string into softtoken key object. */
1596         if ((key_asn = ber_init(&key_octs)) == NULLBER) {
1597                 rv = CKR_GENERAL_ERROR;
1598                 goto error_asn2dhpri;
1599         }
1600 
1601         if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1602                 rv = CKR_WRAPPED_KEY_INVALID;
1603                 goto error_asn2dhpri;
1604         }
1605         /* ... value } end-sequence */
1606         if (size > MAX_DH_KEY) {
1607                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1608                 goto error_asn2dhpri;
1609         }
1610         tmplen = size + 1;
1611         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1612                 rv = CKR_HOST_MEMORY;
1613                 goto error_asn2dhpri;
1614         }
1615         (void) ber_scanf(key_asn, "s",          /* "s}" ? */
1616             tmp.big_value, &tmplen);
1617         tmp.big_value_len = tmplen;
1618         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1619                 free(tmp.big_value);
1620                 goto error_asn2dhpri;
1621         }
1622         free(tmp.big_value);
1623         copy_bigint_attr(&tmp_nopad, KEY_PRI_DH_VALUE(keyp));
1624 
1625         goto cleanup_asn2dhpri;
1626 
1627 error_asn2dhpri:
1628 
1629         bigint_attr_cleanup(KEY_PRI_DH_PRIME(keyp));
1630         bigint_attr_cleanup(KEY_PRI_DH_BASE(keyp));
1631         bigint_attr_cleanup(KEY_PRI_DH_VALUE(keyp));
1632 
1633 cleanup_asn2dhpri:
1634 
1635         if (tmp_nopad.big_value != NULL) {
1636                 (void) memset(tmp_nopad.big_value, 0x0,
1637                     tmp_nopad.big_value_len);
1638                 free(tmp_nopad.big_value);
1639         }
1640 
1641         if (p8obj_asn != NULLBER)
1642                 ber_free(p8obj_asn, 1);
1643 
1644         if (key_octs.bv_val != NULL)
1645                 free(key_octs.bv_val);
1646 
1647         if (key_asn != NULLBER)
1648                 ber_free(key_asn, 1);
1649 
1650         return (rv);
1651 }
1652 
1653 /* Decode ASN.1 BER syntax into DH X9.42 private key. */
1654 static CK_RV
1655 asn1_to_x942_dh_pri(private_key_obj_t *keyp, uchar_t *buf, ulong_t buf_len)
1656 {
1657         CK_RV           rv = CKR_OK;
1658         BerValue        p8obj_octs, key_octs;
1659         BerElement      *p8obj_asn = NULLBER, *key_asn = NULLBER;
1660         ber_len_t       size, tmplen;
1661         char            *cookie;
1662         int             version;
1663         uchar_t         oid[sizeof (DH942_OID) + 1];
1664         biginteger_t    tmp, tmp_nopad = { NULL, 0 };
1665 
1666         p8obj_octs.bv_val = (char *)buf;
1667 #ifdef _LP64
1668         /* LINTED E_CAST_INT_TO_SMALL_INT */
1669         p8obj_octs.bv_len = (ber_len_t)buf_len;
1670 #else
1671         p8obj_octs.bv_len = (ber_len_t)buf_len;
1672 #endif
1673 
1674         key_octs.bv_val = NULL;
1675         key_octs.bv_len = 0;
1676 
1677         /* Decode PKCS#8 object ASN.1, verifying it is DH X9.42 private key. */
1678         if ((p8obj_asn = ber_init(&p8obj_octs)) == NULLBER)
1679                 return (CKR_GENERAL_ERROR);
1680 
1681         /* PKCS#8 PrivateKeyInfo ... */
1682         if (ber_first_element(p8obj_asn, &size, &cookie) != LBER_INTEGER) {
1683                 rv = CKR_WRAPPED_KEY_INVALID;
1684                 goto cleanup_asn2x942dhpri;
1685         }
1686         /* ... begin-sequence { version, */
1687         (void) ber_scanf(p8obj_asn, "i", &version); /* "{i" ? */
1688 
1689         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
1690                 rv = CKR_WRAPPED_KEY_INVALID;
1691                 goto cleanup_asn2x942dhpri;
1692         }
1693         /* ... begin-sequence { */
1694         (void) ber_scanf(p8obj_asn, "{");
1695 
1696         if (ber_next_element(p8obj_asn, &size, cookie) != OID_TAG) {
1697                 rv = CKR_WRAPPED_KEY_INVALID;
1698                 goto cleanup_asn2x942dhpri;
1699         }
1700         /* ... OID, \* DH X9.42 algorithm OID *\ */
1701         if (size != sizeof (DH942_OID)) {
1702                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1703                 goto cleanup_asn2x942dhpri;
1704         }
1705         size = sizeof (oid);
1706         (void) ber_scanf(p8obj_asn, "s", oid, &size);
1707         if (memcmp(oid, DH942_OID, size) != 0) {
1708                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1709                 goto cleanup_asn2x942dhpri;
1710         }
1711 
1712         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
1713                 rv = CKR_WRAPPED_KEY_INVALID;
1714                 goto cleanup_asn2x942dhpri;
1715         }
1716         /* ... begin-sequence { */
1717         (void) ber_scanf(p8obj_asn, "{");
1718 
1719         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1720                 rv = CKR_WRAPPED_KEY_INVALID;
1721                 goto cleanup_asn2x942dhpri;
1722         }
1723         /* ... prime, */
1724         if (size > MAX_DH942_KEY) {
1725                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1726                 goto cleanup_asn2x942dhpri;
1727         }
1728         tmplen = size + 1;
1729         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1730                 rv = CKR_HOST_MEMORY;
1731                 goto cleanup_asn2x942dhpri;
1732         }
1733         (void) ber_scanf(p8obj_asn, "s", tmp.big_value, &tmplen);
1734         tmp.big_value_len = tmplen;
1735         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1736                 free(tmp.big_value);
1737                 goto cleanup_asn2x942dhpri;
1738         }
1739         free(tmp.big_value);
1740         copy_bigint_attr(&tmp_nopad, KEY_PRI_DH942_PRIME(keyp));
1741 
1742         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1743                 rv = CKR_WRAPPED_KEY_INVALID;
1744                 goto error_asn2x942dhpri;
1745         }
1746         /* ... base, */
1747         if (size > MAX_DH942_KEY) {
1748                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1749                 goto error_asn2x942dhpri;
1750         }
1751         tmplen = size + 1;
1752         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1753                 rv = CKR_HOST_MEMORY;
1754                 goto error_asn2x942dhpri;
1755         }
1756         (void) ber_scanf(p8obj_asn, "s", tmp.big_value, &tmplen);
1757         tmp.big_value_len = tmplen;
1758         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1759                 free(tmp.big_value);
1760                 goto error_asn2x942dhpri;
1761         }
1762         free(tmp.big_value);
1763         copy_bigint_attr(&tmp_nopad, KEY_PRI_DH942_BASE(keyp));
1764 
1765         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1766                 rv = CKR_WRAPPED_KEY_INVALID;
1767                 goto error_asn2x942dhpri;
1768         }
1769         /* ... subprime } end-sequence } end-sequence */
1770         if (size > MAX_DH942_KEY) {
1771                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1772                 goto error_asn2x942dhpri;
1773         }
1774         tmplen = size + 1;
1775         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1776                 rv = CKR_HOST_MEMORY;
1777                 goto error_asn2x942dhpri;
1778         }
1779         (void) ber_scanf(p8obj_asn, "s",                /* "s}}" ? */
1780             tmp.big_value, &tmplen);
1781         tmp.big_value_len = tmplen;
1782         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1783                 free(tmp.big_value);
1784                 goto error_asn2x942dhpri;
1785         }
1786         free(tmp.big_value);
1787         copy_bigint_attr(&tmp_nopad, KEY_PRI_DH942_SUBPRIME(keyp));
1788 
1789         if (ber_next_element(p8obj_asn, &size, cookie) != LBER_OCTETSTRING) {
1790                 rv = CKR_WRAPPED_KEY_INVALID;
1791                 goto error_asn2x942dhpri;
1792         }
1793         /* ... DHPrivateKey } end-sequence */
1794         key_octs.bv_len = size + 1;
1795         if ((key_octs.bv_val = malloc(size + 1)) == NULL) {
1796                 rv = CKR_HOST_MEMORY;
1797                 goto error_asn2x942dhpri;
1798         }
1799         (void) ber_scanf(p8obj_asn, "s",                /* "s}" ? */
1800             key_octs.bv_val, &key_octs.bv_len);
1801 
1802         /* Decode key octet string into softtoken key object. */
1803         if ((key_asn = ber_init(&key_octs)) == NULLBER) {
1804                 rv = CKR_GENERAL_ERROR;
1805                 goto error_asn2x942dhpri;
1806         }
1807 
1808         if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1809                 rv = CKR_WRAPPED_KEY_INVALID;
1810                 goto error_asn2x942dhpri;
1811         }
1812         /* ... value } end-sequence */
1813         if (size > MAX_DH942_KEY) {
1814                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1815                 goto error_asn2x942dhpri;
1816         }
1817         tmplen = size + 1;
1818         if ((tmp.big_value = malloc(tmplen)) == NULL) {
1819                 rv = CKR_HOST_MEMORY;
1820                 goto error_asn2x942dhpri;
1821         }
1822         (void) ber_scanf(key_asn, "s",          /* "s}" ? */
1823             tmp.big_value, &tmplen);
1824         tmp.big_value_len = tmplen;
1825         if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1826                 free(tmp.big_value);
1827                 goto error_asn2x942dhpri;
1828         }
1829         free(tmp.big_value);
1830         copy_bigint_attr(&tmp_nopad, KEY_PRI_DH942_VALUE(keyp));
1831 
1832         goto cleanup_asn2x942dhpri;
1833 
1834 error_asn2x942dhpri:
1835 
1836         bigint_attr_cleanup(KEY_PRI_DH942_PRIME(keyp));
1837         bigint_attr_cleanup(KEY_PRI_DH942_BASE(keyp));
1838         bigint_attr_cleanup(KEY_PRI_DH942_SUBPRIME(keyp));
1839         bigint_attr_cleanup(KEY_PRI_DH942_VALUE(keyp));
1840 
1841 cleanup_asn2x942dhpri:
1842 
1843         if (tmp_nopad.big_value != NULL) {
1844                 (void) memset(tmp_nopad.big_value, 0x0,
1845                     tmp_nopad.big_value_len);
1846                 free(tmp_nopad.big_value);
1847         }
1848 
1849         if (p8obj_asn != NULLBER)
1850                 ber_free(p8obj_asn, 1);
1851 
1852         if (key_octs.bv_val != NULL)
1853                 free(key_octs.bv_val);
1854 
1855         if (key_asn != NULLBER)
1856                 ber_free(key_asn, 1);
1857 
1858         return (rv);
1859 }
1860 
1861 /*
1862  * Decode the object key from ASN.1 format into soft_object_t.
1863  */
1864 CK_RV
1865 soft_asn1_to_object(soft_object_t *objp, uchar_t *buf, ulong_t buf_len)
1866 {
1867         CK_RV           rv = CKR_OK;
1868         CK_OBJECT_CLASS class = objp->class;
1869         CK_KEY_TYPE     keytype = objp->key_type;
1870         private_key_obj_t *pvk;
1871 
1872         switch (class) {
1873 
1874         case CKO_PRIVATE_KEY:
1875                 /* Allocate storage for Private Key Object. */
1876                 if ((pvk = calloc(1, sizeof (private_key_obj_t))) == NULL) {
1877                         rv = CKR_HOST_MEMORY;
1878                         return (rv);
1879                 }
1880 
1881                 switch (keytype) {
1882                 case CKK_RSA:
1883                         rv = asn1_to_rsa_pri(pvk, buf, buf_len);
1884                         break;
1885 
1886                 case CKK_DSA:
1887                         rv = asn1_to_dsa_pri(pvk, buf, buf_len);
1888                         break;
1889 
1890                 case CKK_DH:
1891                         rv = asn1_to_dh_pri(pvk, buf, buf_len);
1892                         break;
1893 
1894                 case CKK_X9_42_DH:
1895                         rv = asn1_to_x942_dh_pri(pvk, buf, buf_len);
1896                         break;
1897 
1898                 default:
1899                         rv = CKR_FUNCTION_NOT_SUPPORTED;
1900                         break;
1901 
1902                 } /* keytype */
1903 
1904                 if (rv != CKR_OK)
1905                         free(pvk);
1906                 else
1907                         objp->object_class_u.private_key = pvk;
1908                 break;
1909 
1910         default:
1911                 rv = CKR_FUNCTION_NOT_SUPPORTED;
1912                 break;
1913 
1914         } /* class */
1915 
1916         return (rv);
1917 }