// =================================================================== // // Copyright (c) 2005, Intel Corp. // All rights reserved. // // 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. // * Neither the name of Intel Corporation nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // 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 OWNER 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. // =================================================================== // // vtsp.c // // Higher level interface to TCS for use in service. // // ================================================================== #include #include "tcg.h" #include "tcs.h" #include "bsg.h" #include "log.h" #include "crypto.h" #include "vtsp.h" #include "buffer.h" #define RSA_KEY_SIZE 0x0800 /*********************************************************************************** * GenerateAuth: Generate authorization info to be sent back to application * * Parameters: outParamDigestText The concatenation of output parameters to be SHA1ed * outParamDigestTextSize Size of inParamDigestText * HMACkey Key to be used for HMACing * For OIAP use key.authUsage or PersistStore.ownerAuth * For OSAP use shared secret * pAuth Authorization information from the application * * Return: TPM_SUCCESS Authorization data created * TPM_AUTHFAIL Invalid (NULL) HMACkey presented for OSAP *************************************************************************************/ TPM_RESULT GenerateAuth( /*[IN]*/ const BYTE *inParamDigestText, /*[IN]*/ UINT32 inParamDigestTextSize, /*[IN]*/ const TPM_SECRET *HMACkey, /*[IN,OUT]*/ TCS_AUTH *auth) { if (inParamDigestText == NULL || auth == NULL) return (TPM_AUTHFAIL); else { //Generate new OddNonce Crypto_GetRandom(auth->NonceOdd.nonce, sizeof(TPM_NONCE)); // Create SHA1 inParamDigest TPM_DIGEST inParamDigest; Crypto_SHA1Full(inParamDigestText, inParamDigestTextSize, (BYTE *) &inParamDigest); // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams). BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)]; BSG_PackList( hmacText, 4, BSG_TPM_DIGEST, &inParamDigest, BSG_TPM_NONCE, &(auth->NonceEven), BSG_TPM_NONCE, &(auth->NonceOdd), BSG_TYPE_BOOL, &(auth->fContinueAuthSession) ); Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText), (BYTE *) HMACkey, sizeof(TPM_DIGEST), (BYTE *) &(auth->HMAC)); return(TPM_SUCCESS); } } /*********************************************************************************** * VerifyAuth: Verify the authdata for a command requiring authorization * * Parameters: inParamDigestText The concatenation of parameters to be SHA1ed * inParamDigestTextSize Size of inParamDigestText * authDataUsage AuthDataUsage for the Entity being used * Key->authDataUsage or TPM_AUTH_OWNER * HMACkey Key to be used for HMACing * For OIAP use key.authUsage or PersistStore.ownerAuth * For OSAP use NULL (It will be aquired from the Auth Session) * If unknown (default), assume OIAP * sessionAuth A TCS_AUTH info for the session * pAuth Authorization information from the application * hContext If specified, on failed Auth, VerifyAuth will * generate a new OIAP session in place of themselves * destroyed session. * * Return: TPM_SUCCESS Authorization Verified * TPM_AUTHFAIL Authorization Failed * TPM_FAIL Failure during SHA1 routines *************************************************************************************/ TPM_RESULT VerifyAuth( /*[IN]*/ const BYTE *outParamDigestText, /*[IN]*/ UINT32 outParamDigestTextSize, /*[IN]*/ const TPM_SECRET *HMACkey, /*[IN,OUT]*/ TCS_AUTH *auth, /*[IN]*/ TCS_CONTEXT_HANDLE hContext) { if (outParamDigestText == NULL || auth == NULL) return (TPM_AUTHFAIL); // Create SHA1 inParamDigest TPM_DIGEST outParamDigest; Crypto_SHA1Full(outParamDigestText, outParamDigestTextSize, (BYTE *) &outParamDigest); // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams). TPM_DIGEST hm; BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)]; BSG_PackList( hmacText, 4, BSG_TPM_DIGEST, &outParamDigest, BSG_TPM_NONCE, &(auth->NonceEven), BSG_TPM_NONCE, &(auth->NonceOdd), BSG_TYPE_BOOL, &(auth->fContinueAuthSession) ); Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText), (BYTE *) HMACkey, sizeof(TPM_DIGEST), (BYTE *) &hm); // Compare correct HMAC with provided one. if (memcmp (&hm, &(auth->HMAC), sizeof(TPM_DIGEST)) == 0) { // 0 indicates equality if (!auth->fContinueAuthSession) vtpmloginfo(VTPM_LOG_VTSP_DEEP, "Auth Session: 0x%x closed by TPM by fContinue=0.\n", auth->AuthHandle); return (TPM_SUCCESS); } else { // If specified, reconnect the OIAP session. // NOTE: This only works for TCS's that never have a 0 context. if (hContext) { vtpmloginfo(VTPM_LOG_VTSP_DEEP, "Auth Session: 0x%x closed by TPM due to failure.\n", auth->AuthHandle); VTSP_OIAP( hContext, auth); } return (TPM_AUTHFAIL); } } TPM_RESULT VTSP_OIAP(const TCS_CONTEXT_HANDLE hContext, TCS_AUTH *auth) { vtpmloginfo(VTPM_LOG_VTSP, "OIAP.\n"); TPM_RESULT status = TPM_SUCCESS; TPMTRYRETURN( TCSP_OIAP(hContext, &auth->AuthHandle, &auth->NonceEven) ); memset(&auth->HMAC, 0, sizeof(TPM_DIGEST)); auth->fContinueAuthSession = FALSE; vtpmloginfo(VTPM_LOG_VTSP_DEEP, "Auth Session: 0x%x opened by TPM_OIAP.\n", auth->AuthHandle); goto egress; abort_egress: egress: return status; } TPM_RESULT VTSP_OSAP(const TCS_CONTEXT_HANDLE hContext, const TPM_ENTITY_TYPE entityType, const UINT32 entityValue, const TPM_AUTHDATA *usageAuth, TPM_SECRET *sharedSecret, TCS_AUTH *auth) { vtpmloginfo(VTPM_LOG_VTSP, "OSAP.\n"); TPM_RESULT status = TPM_SUCCESS; TPM_NONCE nonceEvenOSAP, nonceOddOSAP; Crypto_GetRandom((BYTE *) &nonceOddOSAP, sizeof(TPM_NONCE) ); TPMTRYRETURN( TCSP_OSAP( hContext, entityType, entityValue, nonceOddOSAP, &auth->AuthHandle, &auth->NonceEven, &nonceEvenOSAP) ); // Calculating Session Secret BYTE sharedSecretText[TPM_DIGEST_SIZE * 2]; BSG_PackList( sharedSecretText, 2, BSG_TPM_NONCE, &nonceEvenOSAP, BSG_TPM_NONCE, &nonceOddOSAP); Crypto_HMAC(sharedSecretText, sizeof(sharedSecretText), (BYTE *) usageAuth, TPM_DIGEST_SIZE, (BYTE *) sharedSecret); memset(&auth->HMAC, 0, sizeof(TPM_DIGEST)); auth->fContinueAuthSession = FALSE; vtpmloginfo(VTPM_LOG_VTSP_DEEP, "Auth Session: 0x%x opened by TPM_OSAP.\n", auth->AuthHandle); goto egress; abort_egress: egress: return status; } TPM_RESULT VTSP_TerminateHandle(const TCS_CONTEXT_HANDLE hContext, const TCS_AUTH *auth) { vtpmloginfo(VTPM_LOG_VTSP, "Terminate Handle.\n"); TPM_RESULT status = TPM_SUCCESS; TPMTRYRETURN( TCSP_TerminateHandle(hContext, auth->AuthHandle) ); vtpmloginfo(VTPM_LOG_VTSP_DEEP, "Auth Session: 0x%x closed by TPM_TerminateHandle.\n", auth->AuthHandle); goto egress; abort_egress: egress: return status; } TPM_RESULT VTSP_ReadPubek( const TCS_CONTEXT_HANDLE hContext, CRYPTO_INFO *crypto_info) { TPM_RESULT status; TPM_NONCE antiReplay; TPM_DIGEST checksum; BYTE *pubEKtext; UINT32 pubEKtextsize; vtpmloginfo(VTPM_LOG_VTSP, "Reading Public EK.\n"); // GenerateAuth new nonceOdd Crypto_GetRandom(&antiReplay, sizeof(TPM_NONCE) ); TPMTRYRETURN( TCSP_ReadPubek( hContext, antiReplay, &pubEKtextsize, &pubEKtext, &checksum) ); // Extract the remaining output parameters TPM_PUBKEY pubEK; BSG_Unpack(BSG_TPM_PUBKEY, pubEKtext, (BYTE *) &pubEK); // Build CryptoInfo for the bindingKey TPM_RSA_KEY_PARMS rsaKeyParms; BSG_Unpack(BSG_TPM_RSA_KEY_PARMS, pubEK.algorithmParms.parms, &rsaKeyParms); Crypto_RSABuildCryptoInfoPublic(rsaKeyParms.exponentSize, rsaKeyParms.exponent, pubEK.pubKey.keyLength, pubEK.pubKey.key, crypto_info); // Destroy rsaKeyParms BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms); // Set encryption scheme crypto_info->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1; //crypto_info->encScheme = pubEK.algorithmParms.encScheme; crypto_info->algorithmID = pubEK.algorithmParms.algorithmID; goto egress; abort_egress: egress: return status; } TPM_RESULT VTSP_TakeOwnership( const TCS_CONTEXT_HANDLE hContext, const TPM_AUTHDATA *ownerAuth, const TPM_AUTHDATA *srkAuth, CRYPTO_INFO *ek_cryptoInfo, TCS_AUTH *auth) { vtpmloginfo(VTPM_LOG_VTSP, "Taking Ownership of TPM.\n"); TPM_RESULT status = TPM_SUCCESS; TPM_COMMAND_CODE command = TPM_ORD_TakeOwnership; TPM_PROTOCOL_ID proto_id = TPM_PID_OWNER; BYTE *new_srk; BYTE *paramText; // Digest to make Auth. UINT32 paramTextSize; // vars for srkpubkey parameter TPM_KEY srkPub; TPM_KEY_PARMS srkKeyInfo = {TPM_ALG_RSA, TPM_ES_RSAESOAEP_SHA1_MGF1, TPM_SS_NONE, 12, 0}; BYTE srkRSAkeyInfo[12] = { 0x00, 0x00, (RSA_KEY_SIZE >> 8), 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00}; srkKeyInfo.parms = (BYTE *) &srkRSAkeyInfo; struct pack_buf_t srkText; //These values are accurate for an enc(AuthData). struct pack_buf_t encOwnerAuth, encSrkAuth; encOwnerAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256); encSrkAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256); if (encOwnerAuth.data == NULL || encSrkAuth.data == NULL) { vtpmloginfo(VTPM_LOG_VTSP, "Could not malloc encrypted auths.\n"); status = TPM_RESOURCES; goto abort_egress; } Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) ownerAuth, &encOwnerAuth.size, encOwnerAuth.data); Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) srkAuth, &encSrkAuth.size, encSrkAuth.data); // Build srk public key struct srkPub.ver = TPM_STRUCT_VER_1_1; srkPub.keyUsage = TPM_KEY_STORAGE; srkPub.keyFlags = 0x00; srkPub.authDataUsage = TPM_AUTH_ALWAYS; memcpy(&srkPub.algorithmParms, &srkKeyInfo, sizeof(TPM_KEY_PARMS)); srkPub.PCRInfoSize = 0; srkPub.PCRInfo = 0; srkPub.pubKey.keyLength= 0; srkPub.encDataSize = 0; srkText.data = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH); srkText.size = BSG_Pack(BSG_TPM_KEY, (BYTE *) &srkPub, srkText.data); paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH); paramTextSize = BSG_PackList(paramText, 5, BSG_TPM_COMMAND_CODE,&command, BSG_TPM_PROTOCOL_ID, &proto_id, BSG_TPM_SIZE32_DATA, &encOwnerAuth, BSG_TPM_SIZE32_DATA, &encSrkAuth, BSG_TPM_KEY, &srkPub); TPMTRYRETURN( GenerateAuth( paramText, paramTextSize, ownerAuth, auth) ); new_srk = srkText.data; TPMTRYRETURN( TCSP_TakeOwnership ( hContext, proto_id, encOwnerAuth.size, encOwnerAuth.data, encSrkAuth.size, encSrkAuth.data, &srkText.size, &new_srk, auth ) ); paramTextSize = BSG_PackList(paramText, 2, BSG_TPM_RESULT, &status, BSG_TPM_COMMAND_CODE, &command); memcpy(paramText + paramTextSize, new_srk, srkText.size); paramTextSize += srkText.size; TPMTRYRETURN( VerifyAuth( paramText, paramTextSize, ownerAuth, a
/*
    ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
                 2011 Giovanni Di Sirio.

    This file is part of ChibiOS/RT.

    ChibiOS/RT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    ChibiOS/RT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
 * @file    SPC56x/serial_lld.c
 * @brief   SPC563 low level serial driver code.
 *
 * @addtogroup SERIAL
 * @{
 */

#include "ch.h"
#include "hal.h"

#if HAL_USE_SERIAL || defined(__DOXYGEN__)

/*===========================================================================*/
/* Driver exported variables.                                                */
/*===========================================================================*/

/**
 * @brief   eSCI-A serial driver identifier.
 */
#if USE_SPC563_ESCIA || defined(__DOXYGEN__)
SerialDriver SD1;
#endif

/**
 * @brief   eSCI-B serial driver identifier.
 */
#if USE_SPC563_ESCIB || defined(__DOXYGEN__)
SerialDriver SD2;
#endif

/*===========================================================================*/
/* Driver local variables.                                                   */
/*===========================================================================*/

/**
 * @brief   Driver default configuration.
 */
static const SerialConfig default_config = {
  SERIAL_DEFAULT_BITRATE,
  SD_MODE_NORMAL | SD_MODE_PARITY_NONE
};

/*===========================================================================*/
/* Driver local functions.                                                   */
/*===========================================================================*/

/**
 * @brief   eSCI initialization.
 * @details This function must be invoked with interrupts disabled.
 *
 * @param[in] sdp       pointer to a @p SerialDriver object
 * @param[in] config    the architecture-dependent serial driver configuration
 */
static void esci_init(SerialDriver *sdp, const SerialConfig *config) {
  volatile struct ESCI_tag *escip = sdp->escip;
  uint8_t mode = config->sc_mode;

  escip->CR2.R  = 0;                /* MDIS off.                            */
  escip->CR1.R  = 0;
  escip->LCR.R  = 0;
  escip->CR1.B.SBR = SPC563_SYSCLK / (16 * config->sc_speed);
  if (mode & SD_MODE_LOOPBACK)
    escip->CR1.B.LOOPS = 1;
  switch (mode & SD_MODE_PARITY) {
  case SD_MODE_PARITY_ODD:
    escip->CR1.B.PT = 1;
  case SD_MODE_PARITY_EVEN:
    escip->CR1.B.PE = 1;
    escip->CR1.B.M  = 1;            /* Makes it 8 bits data + 1 bit parity. */
  default:
    ;
  }
  escip->LPR.R  = 0;
  escip->CR1.R |= 0x0000002C;       /* RIE, TE, RE to 1.                    */
  escip->CR2.R |= 0x000F;           /* ORIE, NFIE, FEIE, PFIE to 1.         */
}

/**
 * @brief   eSCI de-initialization.
 * @details This function must be invoked with interrupts disabled.
 *
 * @param[in] escip     pointer to an eSCI I/O block
 */
static void esci_deinit(volatile struct ESCI_tag *escip) {

  escip->LPR.R  = 0;
  escip->SR.R   = 0xFFFFFFFF;
  escip->CR1.R  = 0;
  escip->CR2.R  = 0x8000;           /* MDIS on.                             */
}

/**
 * @brief   Error handling routine.
 *
 * @param[in] sdp       pointer to a @p SerialDriver object
 * @param[in] sr        eSCI SR register value
 */
static void set_error(SerialDriver *sdp, uint32_t sr) {
  ioflags_t sts = 0;

  if (sr & 0x08000000)
    sts |= SD_OVERRUN_ERROR;
  if (sr & 0x04000000)
    sts |= SD_NOISE_ERROR;
  if (sr & 0x02000000)
    sts |= SD_FRAMING_ERROR;
  if (sr & 0x01000000)
    sts |= SD_PARITY_ERROR;
/*  if (sr & 0x00000000)
    sts |= SD_BREAK_DETECTED;*/
  chSysLockFromIsr();
  chIOAddFlagsI(sdp, sts);
  chSysUnlockFromIsr();
}

/**
 * @brief   Common IRQ handler.
 *
 * @param[in] sdp       pointer to a @p SerialDriver object
 */
static void serve_interrupt(SerialDriver *sdp) {
  volatile struct ESCI_tag *escip = sdp->escip;

  uint32_t sr = escip->SR.R;
  escip->SR.R = 0x3FFFFFFF;                     /* Does not clear TDRE | TC.*/
  if (sr & 0x0F000000)                          /* OR | NF | FE | PF.       */
    set_error(sdp, sr);
  if (sr & 0x20000000) {                        /* RDRF.                    */
    chSysLockFromIsr();
    sdIncomingDataI(sdp, escip->DR.B.D);
    chSysUnlockFromIsr();
  }
  if (escip->CR1.B.TIE && (sr & 0x80000000)) {  /* TDRE.                    */
    msg_t b;
    chSysLockFromIsr();
    b = chOQGetI(&sdp->oqueue);
    if (b < Q_OK) {
      chIOAddFlagsI(sdp, IO_OUTPUT_EMPTY);
      escip->CR1.B.TIE = 0;
    }
    else {
      ESCI_A.SR.B.TDRE = 1;
      escip->DR.R = (uint16_t)b;
    }
    chSysUnlockFromIsr();
  }
}

#if USE_SPC563_ESCIA || defined(__DOXYGEN__)
static void notify1(GenericQueue *qp) {

  (void)qp;
  if (ESCI_A.SR.B.TDRE) {
    msg_t b = sdRequestDataI(&SD1);
    if (b != Q_EMPTY) {
      ESCI_A.SR.B.TDRE = 1;
      ESCI_A.CR1.B.TIE = 1;
      ESCI_A.DR.R = (uint16_t)b;
    }
  }
}
#endif

#if USE_SPC563_ESCIB || defined(__DOXYGEN__)
static void notify2(GenericQueue *qp) {

  (void)qp;
  if (ESCI_B.SR.B.TDRE) {
    msg_t b = sdRequestDataI(&SD2);
    if (b != Q_EMPTY) {
      ESCI_B.SR.B.TDRE = 1;
      ESCI_B.CR1.B.TIE = 1;
      ESCI_B.DR.R = (uint16_t)b;
    }
  }
}
#endif

/*===========================================================================*/
/* Driver interrupt handlers.                                                */
/*===========================================================================*/

#if USE_SPC563_ESCIA || defined(__DOXYGEN__)
/**
 * @brief   eSCI-A interrupt handler.
 *
 * @isr
 */
CH_IRQ_HANDLER(vector146) {

  CH_IRQ_PROLOGUE();

  serve_interrupt(&SD1);

  CH_IRQ_EPILOGUE();
}
#endif

#if USE_SPC563_ESCIB || defined(__DOXYGEN__)
/**
 * @brief   eSCI-B interrupt handler.
 *
 * @isr
 */
CH_IRQ_HANDLER(vector149) {

  CH_IRQ_PROLOGUE();

  serve_interrupt(&SD2);

  CH_IRQ_EPILOGUE();
}
#endif

/*===========================================================================*/
/* Driver exported functions.                                                */
/*===========================================================================*/

/**
 * @brief   Low level serial driver initialization.
 *
 * @notapi
 */
void sd_lld_init(void) {

#if USE_SPC563_ESCIA
  sdObjectInit(&SD1, NULL, notify1);
  SD1.escip       = &ESCI_A;
  ESCI_A.CR2.R    = 0x8000;                 /* MDIS ON.                     */
  INTC.PSR[146].R = SPC563_ESCIA_PRIORITY;
#endif

#if USE_SPC563_ESCIB
  sdObjectInit(&SD2, NULL, notify2);
  SD2.escip       = &ESCI_B;
  ESCI_B.CR2.R    = 0x8000;                 /* MDIS ON.                     */
  INTC.PSR[149].R = SPC563_ESCIB_PRIORITY;
#endif
}

/**
 * @brief   Low level serial driver configuration and (re)start.
 *
 * @param[in] sdp       pointer to a @p SerialDriver object
 * @param[in] config    the architecture-dependent serial driver configuration.
 *                      If this parameter is set to @p NULL then a default
 *                      configuration is used.
 *
 * @notapi
 */
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {

  if (config == NULL)
    config = &default_config;
  esci_init(sdp, config);
}

/**
 * @brief   Low level serial driver stop.
 *
 * @param[in] sdp       pointer to a @p SerialDriver object
 *
 * @notapi
 */
void sd_lld_stop(SerialDriver *sdp) {

  if (sdp->state == SD_READY)
    esci_deinit(sdp->escip);
}

#endif /* HAL_USE_SERIAL */

/** @} */