/* Microsoft Reference Implementation for TPM 2.0 * * The copyright in this software is being made available under the BSD License, * included below. This software may be subject to other third party and * contributor rights, including patent rights, and no such rights are granted * under this license. * * Copyright (c) Microsoft Corporation * * All rights reserved. * * BSD License * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ //** Includes #include "Tpm.h" #include "X509.h" #include "OIDs.h" #include "TpmASN1_fp.h" #include "X509_ECC_fp.h" #include "X509_spt_fp.h" #include "CryptHash_fp.h" //** Functions //*** X509PushPoint() // This seems like it might be used more than once so... // Return Type: INT16 // > 0 number of bytes added // == 0 failure INT16 X509PushPoint( ASN1MarshalContext *ctx, TPMS_ECC_POINT *p ) { // Push a bit string containing the public key. For now, push the x, and y // coordinates of the public point, bottom up ASN1StartMarshalContext(ctx); // BIT STRING { ASN1PushBytes(ctx, p->y.t.size, p->y.t.buffer); ASN1PushBytes(ctx, p->x.t.size, p->x.t.buffer); ASN1PushByte(ctx, 0x04); } return ASN1EndEncapsulation(ctx, ASN1_BITSTRING); // Ends BIT STRING } //*** X509AddSigningAlgorithmECC() // This creates the singing algorithm data. // Return Type: INT16 // > 0 number of bytes added // == 0 failure INT16 X509AddSigningAlgorithmECC( OBJECT *signKey, TPMT_SIG_SCHEME *scheme, ASN1MarshalContext *ctx ) { PHASH_DEF hashDef = CryptGetHashDef(scheme->details.any.hashAlg); // NOT_REFERENCED(signKey); // If the desired hashAlg definition wasn't found... if(hashDef->hashAlg != scheme->details.any.hashAlg) return 0; switch(scheme->scheme) { #if ALG_ECDSA case TPM_ALG_ECDSA: // Make sure that we have an OID for this hash and ECC if((hashDef->ECDSA)[0] != ASN1_OBJECT_IDENTIFIER) break; // if this is just an implementation check, indicate that this // combination is supported if(!ctx) return 1; ASN1StartMarshalContext(ctx); ASN1PushOID(ctx, hashDef->ECDSA); return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); #endif // ALG_ECDSA default: break; } return 0; } //*** X509AddPublicECC() // This function will add the publicKey description to the DER data. If ctx is // NULL, then no data is transferred and this function will indicate if the TPM // has the values for DER-encoding of the public key. // Return Type: INT16 // > 0 number of bytes added // == 0 failure INT16 X509AddPublicECC( OBJECT *object, ASN1MarshalContext *ctx ) { const BYTE *curveOid = CryptEccGetOID(object->publicArea.parameters.eccDetail.curveID); if((curveOid == NULL) || (*curveOid != ASN1_OBJECT_IDENTIFIER)) return 0; // // // SEQUENCE (2 elem) 1st // SEQUENCE (2 elem) 2nd // OBJECT IDENTIFIER 1.2.840.10045.2.1 ecPublicKey (ANSI X9.62 public key type) // OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named curve) // BIT STRING (520 bit) 000001001010000111010101010111001001101101000100000010... // // If this is a check to see if the key can be encoded, it can. // Need to mark the end sequence if(ctx == NULL) return 1; ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st { X509PushPoint(ctx, &object->publicArea.unique.ecc); // BIT STRING ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 2nd { ASN1PushOID(ctx, curveOid); // curve dependent ASN1PushOID(ctx, OID_ECC_PUBLIC); // (1.2.840.10045.2.1) } ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // Ends SEQUENCE 2nd } return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // Ends SEQUENCE 1st }