blob: 3c6a4e68c9441db8d5ddc5a5a105eccbd1474bbe [file] [log] [blame]
/* 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 "TpmASN1_fp.h"
#include "X509_RSA_fp.h"
#include "X509_spt_fp.h"
#include "CryptHash_fp.h"
#include "CryptRsa_fp.h"
//** Functions
#if ALG_RSA
//*** X509AddSigningAlgorithmRSA()
// This creates the singing algorithm data.
// Return Type: INT16
// > 0 number of bytes added
// == 0 failure
INT16
X509AddSigningAlgorithmRSA(
OBJECT *signKey,
TPMT_SIG_SCHEME *scheme,
ASN1MarshalContext *ctx
)
{
TPM_ALG_ID hashAlg = scheme->details.any.hashAlg;
PHASH_DEF hashDef = CryptGetHashDef(hashAlg);
//
NOT_REFERENCED(signKey);
// return failure if hash isn't implemented
if(hashDef->hashAlg != hashAlg)
return 0;
switch(scheme->scheme)
{
case TPM_ALG_RSASSA:
{
// if the hash is implemented but there is no PKCS1 OID defined
// then this is not a valid signing combination.
if(hashDef->PKCS1[0] != ASN1_OBJECT_IDENTIFIER)
break;
if(ctx == NULL)
return 1;
return X509PushAlgorithmIdentifierSequence(ctx, hashDef->PKCS1);
}
case TPM_ALG_RSAPSS:
// leave if this is just an implementation check
if(ctx == NULL)
return 1;
// In the case of SHA1, everything is default and RFC4055 says that
// implementations that do signature generation MUST omit the parameter
// when defaults are used. )-:
if(hashDef->hashAlg == TPM_ALG_SHA1)
{
return X509PushAlgorithmIdentifierSequence(ctx, OID_RSAPSS);
}
else
{
// Going to build something that looks like:
// SEQUENCE (2 elem)
// OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1)
// SEQUENCE (3 elem)
// [0] (1 elem)
// SEQUENCE (2 elem)
// OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256
// NULL
// [1] (1 elem)
// SEQUENCE (2 elem)
// OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF
// SEQUENCE (2 elem)
// OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256
// NULL
// [2] (1 elem) salt length
// INTEGER 32
// The indentation is just to keep track of where we are in the
// structure
ASN1StartMarshalContext(ctx); // SEQUENCE (2 elements)
{
ASN1StartMarshalContext(ctx); // SEQUENCE (3 elements)
{
// [2] (1 elem) salt length
// INTEGER 32
ASN1StartMarshalContext(ctx);
{
INT16 saltSize =
CryptRsaPssSaltSize((INT16)hashDef->digestSize,
(INT16)signKey->publicArea.unique.rsa.t.size);
ASN1PushUINT(ctx, saltSize);
}
ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 2);
// Add the mask generation algorithm
// [1] (1 elem)
// SEQUENCE (2 elem) 1st
// OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF
// SEQUENCE (2 elem) 2nd
// OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256
// NULL
ASN1StartMarshalContext(ctx); // mask context [1] (1 elem)
{
ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st
// Handle the 2nd Sequence (sequence (object, null))
{
// This adds a NULL, then an OID and a SEQUENCE
// wrapper.
X509PushAlgorithmIdentifierSequence(ctx,
hashDef->OID);
// add the pkcs1-MGF OID
ASN1PushOID(ctx, OID_MGF1);
}
// End outer sequence
ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
}
// End the [1]
ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 1);
// Add the hash algorithm
// [0] (1 elem)
// SEQUENCE (2 elem) (done by
// X509PushAlgorithmIdentifierSequence)
// OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 (NIST)
// NULL
ASN1StartMarshalContext(ctx); // [0] (1 elem)
{
X509PushAlgorithmIdentifierSequence(ctx, hashDef->OID);
}
ASN1EndEncapsulation(ctx, (ASN1_APPLICAIION_SPECIFIC + 0));
}
// SEQUENCE (3 elements) end
ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
// RSA PSS OID
// OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1)
ASN1PushOID(ctx, OID_RSAPSS);
}
// End Sequence (2 elements)
return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
}
default:
break;
}
return 0;
}
//*** X509AddPublicRSA()
// This function will add the publicKey description to the DER data. If fillPtr 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
X509AddPublicRSA(
OBJECT *object,
ASN1MarshalContext *ctx
)
{
UINT32 exp = object->publicArea.parameters.rsaDetail.exponent;
//
/*
SEQUENCE (2 elem) 1st
SEQUENCE (2 elem) 2nd
OBJECT IDENTIFIER 1.2.840.113549.1.1.1 rsaEncryption (PKCS #1)
NULL
BIT STRING (1 elem)
SEQUENCE (2 elem) 3rd
INTEGER (2048 bit) 2197304513741227955725834199357401…
INTEGER 65537
*/
// 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
ASN1StartMarshalContext(ctx); // BIT STRING
ASN1StartMarshalContext(ctx); // SEQUENCE *(2 elem) 3rd
// Get public exponent in big-endian byte order.
if(exp == 0)
exp = RSA_DEFAULT_PUBLIC_EXPONENT;
// Push a 4 byte integer. This might get reduced if there are leading zeros or
// extended if the high order byte is negative.
ASN1PushUINT(ctx, exp);
// Push the public key as an integer
ASN1PushInteger(ctx, object->publicArea.unique.rsa.t.size,
object->publicArea.unique.rsa.t.buffer);
// Embed this in a SEQUENCE tag and length in for the key, exponent sequence
ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // SEQUENCE (3rd)
// Embed this in a BIT STRING
ASN1EndEncapsulation(ctx, ASN1_BITSTRING);
// Now add the formatted SEQUENCE for the RSA public key OID. This is a
// fully constructed value so it doesn't need to have a context started
X509PushAlgorithmIdentifierSequence(ctx, OID_PKCS1_PUB);
return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
}
#endif // ALG_RSA