1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658 |
- /*
- * Copyright (C) 2011-2018 Intel Corporation. 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.
- *
- */
- #include "X509Cert.h"
- #include "sgx_lfence.h"
- #include <cstddef>
- #include <assert.h>
- #define X509_FOR_PSE_PR 1
- #ifdef X509_FOR_PSE_PR
- #include "pse_pr_support.h"
- // used to eliminate `unused variable' warning
- #define UNUSED(val) (void)(val)
- #endif
- #ifndef X509_FOR_PSE_PR
- #include "MeTypes.h"
- #include "SessMgrCommonDefs.h"
- #include "le2be_macros.h"
- #include "CryptoDefs.h"
- #include "romapi/romapi_rsa.h"
- #include "TimeSrv.h"
- #endif // #ifndef X509_FOR_PSE_PR
- #ifdef X509_FOR_PSE_PR
- STATUS CreateSha1Hash
- (
- /*in */ SessMgrDataBuffer *pSrcBuffer,
- /*out*/ SessMgrDataBuffer *pDigest
- )
- {
- PrepareHashSHA1 hash;
- hash.Update(pSrcBuffer->buffer, pSrcBuffer->length);
- if (!hash.Finalize((SHA1_HASH*)pDigest->buffer))
- return X509_GENERAL_ERROR;
- return STATUS_SUCCESS;
- };
- crypto_status_t EcDsa_VerifySignature
- (
- /*in */ const UINT8* pMsg,
- /*in */ uint32_t nMsg,
- /*in */ const EcDsaPubKey* pPublicKey,
- /*in */ const EcDsaSig* pSignature,
- /*out*/ bool* fValid
- )
- {
- crypto_status_t status = CRYPTO_STATUS_INTERNAL_ERROR;
- sgx_ecc_state_handle_t ecc_handle = NULL;
- *fValid = false;
- do
- {
- if (SGX_SUCCESS != sgx_ecc256_open_context(&ecc_handle)) break;
- uint8_t result;
- if ((SGX_SUCCESS == sgx_ecdsa_verify(pMsg, nMsg,
- (sgx_ec256_public_t *)pPublicKey,
- (sgx_ec256_signature_t *)pSignature,
- &result,
- ecc_handle)) && (result == SGX_EC_VALID ))
- *fValid = true;
- status = CRYPTO_STATUS_SUCCESS;
- } while (0);
- if (ecc_handle != NULL) sgx_ecc256_close_context(ecc_handle);
- return status;
- }
- #endif
- //*******************************************************************************************************************************************
- //*******************************************************************************************************************************************
- //*******************************************************************************************************************************************
- static STATUS VerifyBasicCertificateAttributes(const Uint8* certificateDerEncoded, const Uint8* workBuffer, const SessMgrCertificateFields* certificateFields,
- const ISSUER_INFO *IssuerInfo, CertificateType CertType, CertificateLevel CertLevel , BOOL UseFacsimileEpid);
- #ifndef X509_FOR_PSE_PR
- static STATUS VerifyOcspRevocationStatus(SessMgrCertificateFields* certificateFields,
- UINT8 NumberofSingleResponses, OCSP_CERT_STATUS_TABLE * OcspCertStatusTable, ISSUER_INFO *IssuerInfo);
- #endif
- static STATUS VerifySignature(const ISSUER_INFO *IssuerInfo, const SessMgrDataBuffer *MsgBuffer, const SessMgrDataBuffer *SignBuffer, BOOL UseFacsimileEpid);
- #ifndef X509_FOR_PSE_PR
- static void GetPublicKeyDataBuf(SessMgrDataBuffer *PubKeyBuffer, ISSUER_INFO *IssuerInfo);
- static STATUS VerifyOcspCachedResponseValidity(SessMgrOcspResponseFields *OcspResponseFields);
- static STATUS VerifyValidity(SessMgrDateTime notValidBeforeTime, SessMgrDateTime NotValidAfter);
- static STATUS ConvertTimeToNtp(SessMgrDateTime Time, NTP_TIMESTAMP *NtpTime);
- static STATUS StoreTrustedTime(SessMgrDateTime TrustedTime);
- #endif
- #ifndef X509_FOR_PSE_PR
- static STATUS VerifyOcspResponseAttributes(Uint8* OcspRespBuffer, SessMgrOcspResponseFields *ocspResponseFields, ISSUER_INFO* OcspCertRootPublicKey,
- SessMgrDataBuffer Nonce, OCSP_REQ_TYPE OcspReqType, BOOL UseFacsimileEpid);
- static BOOL VerifySha1Hash(SessMgrDataBuffer *HashData, UINT8 *Expectedhash, UINT32 ExpectedHashLength);
- #endif
- static STATUS sessMgrParseDerCert(IN X509_PROTOCOL* X509Protocol, IN Uint8* certificateDerEncoded,
- IN Uint8* pCertEnd, IN Uint8* workBuffer, IN UINT32 workBufferSize,
- OUT SessMgrCertificateFields* certificateFields, IN ISSUER_INFO *IssuerInfo,
- IN BOOL UseFacsimileEpid);
- #ifndef X509_FOR_PSE_PR
- static STATUS sessMgrParseOcspResponse(IN X509_PROTOCOL* X509Protocol, IN Uint8* OcspResponse,
- IN Uint8* OcspResponseEnd, IN Uint8* workBuffer, IN UINT32 workBufferSize,
- OUT SessMgrOcspResponseFields* OcspResponseFields);
- static STATUS ParseBoolean(UINT8 **ppCurrent, UINT8 *pEnd, BOOL* Value, BOOL optional);
- #endif
- static STATUS ParseInteger(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrDataBuffer* DataBuf, BOOL isOptional, BOOL MustBePositive, UINT32 *PaddingLen);
- #ifndef X509_FOR_PSE_PR
- static STATUS ParseOcspExtensions(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrOcspResponseFields* OcspResponseFields);
- static STATUS ParseCertExtensions(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrCertificateFields* certificateFields);
- static STATUS ParseCertificatePolicy(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrDataBuffer *CertificatePolicy);
- #endif
- static STATUS ParseSubjectPublicKeyInfo(UINT8 **ppCurrent, UINT8 *pEnd, UINT8 **pworkbuffer, SessMgrCertificateFields* certificateFields);
- static STATUS ParseRsaPublicKey(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrRsaKey * RsaKey);
- static STATUS ParseEpidPublicKey(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrEpidGroupPublicKey * EpidKey);
- static STATUS ParseEcdsaPublicKey(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrEcdsaPublicKey * EcDsaKey, SessMgrEllipticCurveParameter params);
- static STATUS ParseOID(UINT8 **ppCurrent, UINT8 *pEnd, UINT32 *EnumVal, const UINT8 *OidList, UINT32 Max_Entries, UINT32 EntrySize );
- static STATUS ParseSignatureValue(UINT8 **ppCurrent, UINT8 *pEnd, UINT8 **pworkbuffer, UINT32 WorkBufferSize, SessMgrDataBuffer *SignatureValueBuf, UINT8 SignatureAlgoId);
- static STATUS ParseAlgoIdentifier(UINT8 **ppCurrent, UINT8 *pEnd, UINT32* algoId, AlgorithmTypes Type, SessMgrEllipticCurveParameter *params);
- static STATUS ParseAlgoParameters(UINT8 **ppCurrent, UINT8 *pEnd, UINT32* param);
- static STATUS ParseName(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrX509Name* Name);
- static STATUS ParseTime(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrDateTime* DateTime);
- static STATUS DecodeLength(UINT8* Buffer, UINT8* BufferEnd, UINT32* Length, UINT8* EncodingBytes);
- static void SwapEndian(UINT8* ptr, int length);
- static STATUS swapendian_memcpy(UINT8 *DestPtr, UINT32 DestLen, UINT8 *SrcPtr, UINT32 SrcLen);
- static STATUS ParseIdAndLength(UINT8 **ppCurrent, UINT8 *pEnd, UINT8 ExpectedId, UINT32* Length, UINT8* EncodingBytes, BOOL Optional);
- #ifndef X509_FOR_PSE_PR
- static int Pow(int num, int exp);
- #endif
- /* This list should always be synced up with the SessMgrAlgorithmOid enum */
- const UINT8 HardCodedSignatureAlgorithmOid[][9] =
- {
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x02},
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x03},
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04},
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05},
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x07},
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x08},
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x09},
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0a},
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0b},
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0c},
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0d},
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0e},
- {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x01},
- {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02},
- };
- const UINT8 HardCodedPublicKeyAlgorithmOid[][10] =
- {
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01},
- {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01},
- {0x2A, 0x86, 0x48, 0x86, 0xf8, 0x4d, 0x01, 0x09, 0x04, 0x01},
- {0x2A, 0x86, 0x48, 0x86, 0xf8, 0x4d, 0x01, 0x09, 0x04, 0x02},
- {0x2A, 0x86, 0x48, 0x86, 0xf8, 0x4d, 0x01, 0x09, 0x04, 0x03},
- };
- const UINT8 HashAlgorithmOid[][9] =
- {
- {0x2B, 0x0E, 0x03, 0x02, 0x1A},
- {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01},
- };
- /* This list should always be synced up with the NameStruct enum */
- const UINT8 HardCodedNameOid[][10] =
- {
- {0x55, 0x04, 0x03},
- {0x55, 0x04, 0x0a},
- {0x55, 0x04, 0x06},
- {0x55, 0x04, 0x07},
- {0x55, 0x04, 0x08},
- {0x55, 0x04, 0x0b},
- {0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x01},
- };
- #ifndef X509_FOR_PSE_PR
- const UINT8 CertExtensionOid[][9] =
- {
- {0x55, 0x1d, 0x23},
- {0x55, 0x1d, 0x0E},
- {0x55, 0x1d, 0x0F},
- {0x55, 0x1d, 0x13},
- {0x55, 0x1d, 0x20},
- {0x55, 0x1d, 0x25},
- {0x2A, 0x86, 0x48, 0x86, 0xF8, 0x4D, 0x01, 0x09, 0x02},
- };
- const UINT8 OcspExtensionOid[][9] =
- {
- {0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02}, // 1.3.6.1.5.5.7.48.1.2
- };
- #endif
- const UINT8 EllipticCurveOid[][8] =
- {
- {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}
- };
- #ifndef X509_FOR_PSE_PR
- const UINT8 CertificatePolicyOid[][9] =
- {
- {0x2A, 0x86, 0x48, 0x86, 0xF8, 0x4d, 0x01, 0x09, 0x01}
- };
- const UINT8 CertificatePolicyQualifierIdOid[][8] =
- {
- {0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01}
- };
- const UINT8 OcspResponseTypeOid[][9] =
- {
- {0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01}
- };
- const UINT8 ExtendedKeyUsageOcspSignOid[][8] =
- {
- 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x09
- };
- #endif
- #ifndef X509_FOR_PSE_PR
- /*
- ParseOcspResponseChain - Decodes a DER encoded X.509 OCSP response and makes a list of the serial numbers and hashes from the OCSP response.
- @param OcspRespBuffer - If not NULL, contains the OCSP response. OCSP response contains a list of certificates with their current status (good/revoked)
- @param OcspRespBufferLength - Total Length of the OCSP response
- @param OcspCertRootPublicKey - Public key used to sign the first certificate in the chain. This is the root of trust. If NULL, Intel public key is used.
- @param OcspCertStatusTable - Table containing interesting fields in the OCSP response which will be used to compare against the verifier certificate.
- @param NumberOfSingleResponses - Number of single responses that the OCSP response has returned to us.
- @param Nonce - Contains the Nonce that was sent. If nonce Exists, the OCSP response should have a nonce extension that contains the same values.
- @retval X509_STATUS_SUCCESS - The operation completed successfully.
- @retval STATUS_INVALID_VERSION
- @retval STATUS_UNSUPPORTED_ALGORITHM
- @retval STATUS_ENCODING_ERROR
- @retval STATUS_INVALID_ARGS
- @retval STATUS_UNSUPPORTED_CRITICAL_EXTENSION
- @retval STATUS_UNSUPPORTED_TYPE
- */
- STATUS ParseOcspResponseChain( UINT8* OcspRespBuffer,
- UINT32 OcspRespBufferLength,
- UINT8* workBuffer,
- UINT32 workBufferSize,
- ISSUER_INFO* OcspCertRootPublicKey,
- OCSP_CERT_STATUS_TABLE *OcspCertStatusTable,
- UINT8* NumberOfSingleResponses,
- SessMgrDataBuffer Nonce,
- OCSP_REQ_TYPE OcspReqType,
- BOOL UseFacsimileEpid)
- {
- STATUS Status;
- UINT32 Length = 0;
- UINT32 OcspResponseLength = 0;
- UINT8 TableIndex = 0;
- SessMgrOcspSingleResponse *SingleResponse;
- int i;
- SessMgrOcspResponseFields OcspResponseFields;
- UINT8 EncodingBytes; // number of bytes used for encoding into ASN DER format
- UINT8 *current_ptr = OcspRespBuffer;
- UINT8 *end_of_ocsp_response_chain = OcspRespBuffer + OcspRespBufferLength;
- // Workaround for Windows OCSP responder shortcoming. Loop through OCSP response
- // We will loop through each of the OCSP responses, verify the OCSP responder certificate and
- while(current_ptr < end_of_ocsp_response_chain){
- Status = DecodeLength(current_ptr + 1, end_of_ocsp_response_chain, &Length, &EncodingBytes);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- OcspResponseLength = Length + EncodingBytes + 1;
- memset(workBuffer, 0, workBufferSize);
- memset(&OcspResponseFields, 0, sizeof(OcspResponseFields));
- Status = sessMgrParseOcspResponse( NULL, current_ptr, current_ptr + OcspResponseLength, workBuffer, workBufferSize, &OcspResponseFields);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- Status = VerifyOcspResponseAttributes(NULL, &OcspResponseFields, NULL, Nonce, OcspReqType, UseFacsimileEpid);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_OCSP_VERIFICATION_FAILED;
- }
- // copy the interesting data
- for(i=0;i<OcspResponseFields.numberOfSingleReponses;i++){
- SingleResponse = (SessMgrOcspSingleResponse *)(OcspResponseFields.allResponses) + i;
- Status = VerifyValidity(SingleResponse->thisUpdate, SingleResponse->nextUpdate);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_OCSP_VERIFICATION_FAILED;
- }
- if(SingleResponse->ocspCertificateStatus == good){
- if(TableIndex == MAX_CERT_CHAIN_LENGTH){
- DBG_ASSERT(0);
- return X509_STATUS_OCSP_VERIFICATION_FAILED;
- }
- SESSMGR_MEMCPY_S(OcspCertStatusTable[TableIndex].serialNumber, sizeof(OcspCertStatusTable[TableIndex].serialNumber),
- SingleResponse->serialNumber.buffer, SingleResponse->serialNumber.length);
- DBG_ASSERT(SingleResponse->serialNumber.length <= 255);
- OcspCertStatusTable[TableIndex].SerialNumberSize = (UINT8)SingleResponse->serialNumber.length;
- SESSMGR_MEMCPY_S(OcspCertStatusTable[TableIndex].issuerKeyHash, sizeof(OcspCertStatusTable[TableIndex].issuerKeyHash),
- SingleResponse->issuerKeyHash.buffer, SingleResponse->issuerKeyHash.length);
- DBG_ASSERT(SingleResponse->issuerKeyHash.length <= 255);
- OcspCertStatusTable[TableIndex].issuerKeyHashSize = (UINT8)SingleResponse->issuerKeyHash.length;
- SESSMGR_MEMCPY_S(OcspCertStatusTable[TableIndex].issuerNameHash, sizeof(OcspCertStatusTable[TableIndex].issuerNameHash),
- SingleResponse->issuerNameHash.buffer, SingleResponse->issuerNameHash.length);
- DBG_ASSERT(SingleResponse->issuerNameHash.length <= 255);
- OcspCertStatusTable[TableIndex].issuerNameHashSize = (UINT8)SingleResponse->issuerNameHash.length;
- OcspCertStatusTable[TableIndex].HashAlgo = SingleResponse->issuerIdentifierHashType;
- TableIndex++;
- }
- }
- current_ptr += OcspResponseLength;
- }
- if (current_ptr != end_of_ocsp_response_chain){
- DBG_ASSERT(0);
- return X509_STATUS_INVALID_ARGS;
- }
- *NumberOfSingleResponses = TableIndex;
- return STATUS_SUCCESS;
- }
- #endif
- /*
- ParseCertificateChain - This function can
- - parse a certificate chain and return the CertificateFields of all the last certificate (usually the certificate of interest)
- - optionally take in root public key that was used to sign first certificate in the chain. If NULL, Intel public Key is used.
- - optionally take in ocspRespBuffer. If ocspRespBuffer is not NULL, this function will parse the ocsp response cert, make a list of
- certificates authenticated by OCSP responder, and use this list to verify if each certificate in the chain has been authenticated.
- - optionally takes in the root public key used to sign the first certifcate in the OCSP responders certificate.
- @param pCertChain - Pointer to the certificate chain. The first certificate in the chain is assumed to be Intel signed if root public key (arg 4) is NULL
- @param CertChainLength - Length of the certificate chain
- @param certificateFields - Data structure containing parsed output of the last certificate in the chain (usually the certificate of interest))
- @param RootPublicKey - Public key used to sign the first certificate in the chain. This is the root of trust. If NULL, Intel public key is used.
- @param NumberOfSingleResponses - Number of single responses that the OCSP response has returned to us.
- @param OcspCertStatusTable - Table containing interesting fields in the OCSP response which will be used to compare against the verifier certificate.
- @param VerifierCert - Contains pointer and length of the VerifierCertificate. If non NULL, the final certificate in the chain is populated with this Data.
- @param CertType - Indicates what type of certificate we are processing.Some checks are specific to certain types of certs.
- @retval X509_STATUS_SUCCESS - The operation completed successfully.
- */
- /* Input:
- pointer to buffer containing a chain of certificates
- Total Length
- Assumes the first certificate in the chain is signed by Intel
- */
- STATUS ParseCertificateChain(UINT8 *pCertChain,
- UINT32 CertChainLength,
- SessMgrCertificateFields *certificateFields,
- UINT8 *CertWorkBuffer,
- UINT32 CertWorkBufferLength,
- ISSUER_INFO *RootPublicKey,
- UINT8 NumberOfSingleResponses,
- OCSP_CERT_STATUS_TABLE *OcspCertStatusTable,
- CertificateType CertType,
- BOOL UseFacsimileEpid
- )
- {
- STATUS Status;
- UINT8 CertCount = 0;
- SessMgrEcdsaPublicKey ecdsa_pub_key;
- // This is the temp buffer used to store the issuer signing key to verify the next certificate in the chain.
- // This size of this buffer should be equal to the Max possible key size
- UINT8 TempSignKeyBuffer[200];
- SessMgrDataBuffer TempDataBuffer;
- UINT8 *pCert;
- UINT8 *pCertChainEnd;
- UINT32 CertLength = 0;
- UINT8 EncodingBytes; // number of bytes used for encoding into ASN DER format
- int MaxChainLengthAllowed = 0xFF; // This is to enforce the PathLen Basic Constraints.
- UINT8 HashOut[SHA1_HASH_LEN] = {0};
- UINT8 *KeyBufPtr;
- CertificateLevel CertLevel;
- ISSUER_INFO IssuerInfo;
- #ifdef X509_FOR_PSE_PR
- UNUSED(NumberOfSingleResponses);
- #endif
- if (pCertChain == NULL ||
- pCertChain + CertChainLength <= pCertChain ||
- CertWorkBuffer == NULL ||
- CertWorkBuffer + CertWorkBufferLength <= CertWorkBuffer)
- {
- return X509_STATUS_INVALID_ARGS;
- }
- memset(&IssuerInfo, 0 , sizeof(ISSUER_INFO));
- pCert = pCertChain;
- pCertChainEnd = pCertChain + CertChainLength;
- CertLevel = root;
- if(!RootPublicKey){
- // always use debug keys except for EPID group certs
- #ifdef X509_FOR_PSE_PR
- ecdsa_pub_key.px = SerializedPublicKey;
- ecdsa_pub_key.py = SerializedPublicKey + 32;
- #else
- if(gSessmgrCtx.FuseGidZero == FALSE){
- ecdsa_pub_key.px = INTEL_ECDSA_PUBKEY_PROD_BE;
- ecdsa_pub_key.py = INTEL_ECDSA_PUBKEY_PROD_BE + 32;
- }else{
- ecdsa_pub_key.px = INTEL_ECDSA_PUBKEY_DBG_BE;
- ecdsa_pub_key.py = INTEL_ECDSA_PUBKEY_DBG_BE + 32;
- }
- #endif
- ecdsa_pub_key.eccParameter = curvePrime256v1;
- IssuerInfo.buffer = (UINT8 *)&ecdsa_pub_key;
- IssuerInfo.length = sizeof(ecdsa_pub_key);
- IssuerInfo.AlgoType = X509_ecdsa_with_SHA256;
- }else{
- // Not allowing user to pass their own root key.
- DBG_ASSERT(0);
- return X509_STATUS_INVALID_ARGS;
- // memcpy(&IssuerInfo, RootPublicKey, sizeof(IssuerInfo));
- }
- // Set this up for the hash.
- IssuerInfo.EncodedPublicKeyHashBuffer.buffer = HashOut;
- IssuerInfo.EncodedPublicKeyHashBuffer.length = SHA1_HASH_LEN;
- // For root key, populate the ISSUER_INFO data structure. Refer to data strucutre definition for more details.
- // use the temp sign key buffer for this purpose.
- memset(TempSignKeyBuffer, 0 , sizeof(TempSignKeyBuffer));
- TempDataBuffer.buffer = TempSignKeyBuffer;
- KeyBufPtr = TempSignKeyBuffer;
- *KeyBufPtr = 0x04;
- KeyBufPtr++;
- SESSMGR_MEMCPY_S(KeyBufPtr, sizeof(TempSignKeyBuffer) - 1, ecdsa_pub_key.px, ECDSA_KEY_ELEMENT_SIZE);
- KeyBufPtr += ECDSA_KEY_ELEMENT_SIZE;
- SESSMGR_MEMCPY_S(KeyBufPtr, sizeof(TempSignKeyBuffer) - 1 - ECDSA_KEY_ELEMENT_SIZE, ecdsa_pub_key.py, ECDSA_KEY_ELEMENT_SIZE);
- TempDataBuffer.length = ECDSA_KEY_SIZE + 1; // +1 to reflect the addition of 0x04 in the beginning of the buffer.
- Status = CryptoCreateHash(CRYPTO_HASH_TYPE_SHA1,
- &TempDataBuffer,
- &IssuerInfo.EncodedPublicKeyHashBuffer,
- NULL,
- NULL,
- SINGLE_BLOCK);
- if(Status != STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_INTERNAL_ERROR;
- }
- while(pCert < pCertChainEnd)
- {
- //
- // very, very doubtful we get here speculatively
- // with NULL pCert, but between that and possibility
- // of looping too many times, add lfence
- //
- sgx_lfence();
- /* certificate always starts with a sequence followed by length at offset 1. */
- CHECK_ID(*pCert, DER_ENCODING_SEQUENCE_ID);
- if ((pCert + 1) == pCertChainEnd) {
- break;
- }
- Status = DecodeLength(pCert + 1, pCertChainEnd, &CertLength, &EncodingBytes);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return Status;
- }
- CertLength = CertLength + EncodingBytes + 1;
- if( (pCert + CertLength) >= pCertChainEnd){
- // if this is the last certificate in the chain, it is the leaf
- CertLevel = leaf;
- }
- // Check Basic Constraints Compliance
- if(MaxChainLengthAllowed <= 0 && CertLevel != leaf){
- // We have one more CA which is violating the basic constraints set by somebody. return error
- DBG_ASSERT(0);
- return X509_STATUS_BASIC_CONSTRAINTS_VIOLATION;
- }
- memset(certificateFields, 0, sizeof(SessMgrCertificateFields));
- memset(CertWorkBuffer, 0, CertWorkBufferLength);
- certificateFields->productType = invalidProductType;
- Status = sessMgrParseDerCert(NULL, pCert, pCert + CertLength, CertWorkBuffer, CertWorkBufferLength, certificateFields, &IssuerInfo, UseFacsimileEpid);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return Status;
- }
- // First Certificate is always intel signed
- Status = VerifyBasicCertificateAttributes(pCert, CertWorkBuffer, certificateFields, &IssuerInfo, CertType, CertLevel, UseFacsimileEpid);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return Status;
- }
- // Verifiation is required if OCSP table exists (even if empty), make sure the certificate has not been revoked
- if(OcspCertStatusTable){
- BOOL IntelSelfSignedRoot = false;
- #ifdef X509_FOR_PSE_PR
- if(CertLevel == root && memcmp(certificateFields->EncodedSubjectPublicKey.buffer+1, SerializedPublicKey, sizeof(SerializedPublicKey)) == 0)
- IntelSelfSignedRoot = true;
- #else
- if(CertLevel == root && memcmp(certificateFields->EncodedSubjectPublicKey.buffer+1, INTEL_ECDSA_PUBKEY_PROD_BE, sizeof(INTEL_ECDSA_PUBKEY_PROD_BE)) == 0)
- IntelSelfSignedRoot = true;
- else if(gSessmgrCtx.FuseGidZero && CertLevel == root && memcmp(certificateFields->EncodedSubjectPublicKey.buffer+1, INTEL_ECDSA_PUBKEY_DBG_BE, sizeof(INTEL_ECDSA_PUBKEY_DBG_BE)) == 0)
- IntelSelfSignedRoot = true;
- #endif
- // Skip revocation status check for Intel self-signed root certificate
- if(!IntelSelfSignedRoot) {
- #ifndef X509_FOR_PSE_PR
- Status = VerifyOcspRevocationStatus(certificateFields, NumberOfSingleResponses, OcspCertStatusTable, &IssuerInfo);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_OCSP_FAILURE;
- }
- #endif
- }
- }
- // Certificate has been verified. Everything is good.
- // if this is not the leaf, store the public key and algorithm type to use in next certificate signature verification
- if(CertLevel != leaf){
- memset(TempSignKeyBuffer, 0, sizeof(TempSignKeyBuffer));
- SESSMGR_MEMCPY_S(TempSignKeyBuffer, sizeof(TempSignKeyBuffer), certificateFields->subjectPublicKey.buffer, certificateFields->subjectPublicKey.length);
- // Clear the issuer info structure.
- memset(&IssuerInfo, 0 , sizeof(ISSUER_INFO));
- // This key is the issuer key for the next certificate. Populate the IssuerInfo
- IssuerInfo.buffer = TempSignKeyBuffer;
- IssuerInfo.length = certificateFields->subjectPublicKey.length;
- IssuerInfo.AlgoType = certificateFields->algorithmIdentifierForSignature;
- // Set this up for the hash.
- IssuerInfo.EncodedPublicKeyHashBuffer.buffer = HashOut;
- IssuerInfo.EncodedPublicKeyHashBuffer.length = SHA1_HASH_LEN;
- Status = CryptoCreateHash(CRYPTO_HASH_TYPE_SHA1,
- &certificateFields->EncodedSubjectPublicKey,
- &IssuerInfo.EncodedPublicKeyHashBuffer,
- NULL,
- NULL,
- SINGLE_BLOCK);
- if(Status != STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_INTERNAL_ERROR;
- }
- // We might have zero or more intermediate certificates
- CertLevel = intermediate;
- // Record and Verify Basic Path Len Constraints. Refer to RFC for details on Basic constrains path len extensions.
- // If PathLen constraint set by this CA is more constrained than the one enforced by the previous CA, update MaxChainLength
- if(certificateFields->basicConstraint.isBasicConstraintPresent && certificateFields->basicConstraint.pathLenConstraint < (UINT32)MaxChainLengthAllowed)
- MaxChainLengthAllowed = certificateFields->basicConstraint.pathLenConstraint;
- else
- MaxChainLengthAllowed--;
- IssuerInfo.CommonNameBuf.buffer = (UINT8 *)certificateFields->subject.commonName;
- IssuerInfo.CommonNameBuf.length = certificateFields->subject.commonNameSize;
- IssuerInfo.productType = certificateFields->productType;
- }
- pCert += CertLength;
- CertCount++;
- }
- if (pCert != pCertChainEnd) {
- DBG_ASSERT(0);
- return X509_STATUS_INVALID_ARGS;
- }
- return X509_STATUS_SUCCESS;
- }
- #ifndef X509_FOR_PSE_PR
- /*
- This function compares the serial number of the certificate with the list of certificates that the OCSP responder sent us.
- If found, Make sure the status of the certificate is not revoked.
- */
- STATUS VerifyOcspRevocationStatus(SessMgrCertificateFields* certificateFields,
- UINT8 NumberofSingleResponses,
- OCSP_CERT_STATUS_TABLE* OcspCertStatusTable,
- ISSUER_INFO *IssuerInfo)
- {
- UINT32 i;
- STATUS Status;
- STATUS VerificationStatus = X509_STATUS_OCSP_VERIFICATION_FAILED;
- SessMgrDataBuffer HashBuf;
- SessMgrDataBuffer IssuerNameBuf;
- UINT8 HashOut[SHA1_HASH_LEN] = {0};
- HashBuf.buffer = HashOut;
- HashBuf.length = SHA1_HASH_LEN;
- IssuerNameBuf.buffer = (UINT8 *)certificateFields->issuer.DistinguishedName;
- IssuerNameBuf.length = certificateFields->issuer.DistinguishedNameSize;
- for (i=0;i<NumberofSingleResponses;i++){
- // Check serial number
- if(certificateFields->serialNumber.length != OcspCertStatusTable[i].SerialNumberSize ||
- memcmp(certificateFields->serialNumber.buffer, OcspCertStatusTable[i].serialNumber, OcspCertStatusTable[i].SerialNumberSize) != 0) {
- continue;
- }
- // Check hash key
- if(IssuerInfo->EncodedPublicKeyHashBuffer.length != OcspCertStatusTable[i].issuerKeyHashSize ||
- memcmp(IssuerInfo->EncodedPublicKeyHashBuffer.buffer, OcspCertStatusTable[i].issuerKeyHash, OcspCertStatusTable[i].issuerKeyHashSize) != 0){
- continue;
- }
- memset(HashBuf.buffer, 0, SHA1_HASH_LEN);
- Status = CryptoCreateHash(CRYPTO_HASH_TYPE_SHA1,
- &IssuerNameBuf,
- &HashBuf,
- NULL,
- NULL,
- SINGLE_BLOCK);
- if(Status != STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_INTERNAL_ERROR;
- }
- // Check issuer name
- if(SHA1_HASH_LEN != OcspCertStatusTable[i].issuerNameHashSize ||
- memcmp(HashBuf.buffer, OcspCertStatusTable[i].issuerNameHash, OcspCertStatusTable[i].issuerNameHashSize) != 0){
- continue;
- }
- // The certificate has been found in the OCSP response, break and return success
- VerificationStatus = X509_STATUS_SUCCESS;
- break;
- }
- DBG_ASSERT(VerificationStatus == X509_STATUS_SUCCESS);
- return VerificationStatus;
- }
- #endif
- #ifndef X509_FOR_PSE_PR
- /*
- This function will accept the algorithm and the keys as a void pointer and will verify the keys accordingly.
- */
- #define SESSMGR_RSA_WORK_BUFFER_SIZE (ROM_RSA_WIN_EXP_1_BUFFER_SIZE + 2*(RSA_KEY_SIZE_2048_BYTES))
- UINT8 RsaWorkBuffer[SESSMGR_RSA_WORK_BUFFER_SIZE];
- #endif // #ifndef X509_FOR_PSE_PR
- STATUS VerifySignature(const ISSUER_INFO *IssuerInfo, const SessMgrDataBuffer *MsgBuffer, const SessMgrDataBuffer *SignBuffer, BOOL UseFacsimileEpid)
- {
- #ifdef X509_FOR_PSE_PR
- BOOL VerifRes = FALSE;
- #else
- BOOL VerifRes = FALSE;
- SessMgrDataBuffer LocalSignBuffer;
- SessMgrDataBuffer LocalMsgBuffer;
- ROM_RSA_DATA_BUFFER workBuffer;
- ROM_RSA_VERIFY_PARAMS RsaVerifyParams;
- UINT8 RsaEBuffer[RSA_E_SIZE] = {0, 0 ,0 ,0};
- UINT8 RsaNBuffer[RSA_KEY_SIZE_2048_BYTES] = {0};
- #endif
- SessMgrEcdsaPublicKey *PublicKeyFromCert;
- PseEcdsaPublicKey EcdsaKey;
- G3Point* g3point;
- #ifndef X509_FOR_PSE_PR
- UINT32 hashSize = 0;
- BOOL IsSignatureValid = FALSE;
- SessMgrRsaKey *RsaKeyFromCert;
- #endif
- STATUS Status = X509_INVALID_SIGNATURE;
- #ifdef X509_FOR_PSE_PR
- UNUSED(UseFacsimileEpid);
- #endif
- do{
- switch(IssuerInfo->AlgoType){
- case X509_ecdsa_with_SHA1:
- Status = X509_STATUS_UNSUPPORTED_ALGORITHM;
- break;
- case X509_ecdsa_with_SHA256:
- PublicKeyFromCert = (SessMgrEcdsaPublicKey *)(IssuerInfo->buffer);
- SESSMGR_MEMCPY_S(EcdsaKey.px, sizeof(EcdsaKey.px), PublicKeyFromCert->px, 32);
- SESSMGR_MEMCPY_S(EcdsaKey.py, sizeof(EcdsaKey.py), PublicKeyFromCert->py, 32);
- // Allocate DWORD aligned local buffers for Signature and Msg.
- // Swap Key and signature Convert Intel signature of the parameters certificate prior verifying it
- g3point = reinterpret_cast<G3Point*>(EcdsaKey.px);
- SwapEndian_32B(g3point->x);
- SwapEndian_32B(g3point->y);
- SwapEndian_32B(reinterpret_cast<G3Point*>(SignBuffer->buffer)->x);
- SwapEndian_32B(reinterpret_cast<G3Point*>(SignBuffer->buffer)->y);
- #ifndef X509_FOR_PSE_PR
- void* pCtx = NULL;
- pCtx = UseFacsimileEpid ? gSessmgrCtx.KeysCtxFacsimile : gSessmgrCtx.KeysCtx;
- #endif
- Status = SafeIdSigmaEcDsaVerifyPriv( pCtx,
- MsgBuffer->buffer,
- MsgBuffer->length,
- (unsigned char *)&EcdsaKey,
- (unsigned char *)SignBuffer->buffer,
- CRYPTO_HASH_TYPE_SHA256,
- 0,
- 32,
- &VerifRes);
- if(Status != STATUS_SUCCESS){
- DBG_ASSERT(0);
- Status = SESSMGR_STATUS_INTERNAL_ERROR;
- break;
- }
- #ifndef X509_FOR_PSE_PR
- // Testing workaround: always allow production signed on SSKU part
- if(VerifRes == FALSE) {
- if(gSessmgrCtx.FuseGidZero)
- {
- Status = SafeIdSigmaEcDsaVerifyPriv(UseFacsimileEpid ? gSessmgrCtx.KeysCtxFacsimile : gSessmgrCtx.KeysCtx,
- MsgBuffer->buffer,
- MsgBuffer->length,
- INTEL_ECDSA_PUBKEY_PROD_LE,
- (unsigned char *)SignBuffer->buffer,
- CRYPTO_HASH_TYPE_SHA256,
- 0,
- 32,
- &VerifRes);
- DBG_ASSERT(Status == STATUS_SUCCESS);
- }
- if(VerifRes == FALSE) {
- DBG_ASSERT(0);
- return X509_INVALID_SIGNATURE;
- }
- }
- #else
- if(VerifRes == FALSE) {
- return X509_INVALID_SIGNATURE;
- }
- #endif
- // convert back
- g3point = reinterpret_cast<G3Point*>(EcdsaKey.px);
- SwapEndian_32B(g3point->x);
- SwapEndian_32B(g3point->y);
- SwapEndian_32B((reinterpret_cast<G3Point*>(SignBuffer->buffer))->x);
- SwapEndian_32B((reinterpret_cast<G3Point*>(SignBuffer->buffer))->y);
- break;
- case X509_sha1withRSAEncryption:
- case X509_sha256WithRSAEncryption:
- #ifdef X509_FOR_PSE_PR
- Status = X509_STATUS_UNSUPPORTED_ALGORITHM;
- #else
- RsaKeyFromCert = (SessMgrRsaKey *)(IssuerInfo->buffer);
- DBG_ASSERT(RsaKeyFromCert->n.length == RSA_KEY_SIZE_2048_BYTES);
- SESSMGR_MEMCPY_S(RsaEBuffer + sizeof(RsaEBuffer) - RsaKeyFromCert->e.length, RsaKeyFromCert->e.length, RsaKeyFromCert->e.buffer, RsaKeyFromCert->e.length);
- RsaKeyFromCert->e.buffer = RsaEBuffer;
- RsaKeyFromCert->e.length = RSA_E_SIZE;
- SESSMGR_MEMCPY_S(RsaNBuffer + RSA_KEY_SIZE_2048_BYTES - RsaKeyFromCert->n.length, RsaKeyFromCert->n.length, RsaKeyFromCert->n.buffer, RsaKeyFromCert->n.length);
- RsaKeyFromCert->n.buffer = RsaNBuffer;
- RsaKeyFromCert->n.length = RSA_KEY_SIZE_2048_BYTES;
- workBuffer.length = SESSMGR_RSA_WORK_BUFFER_SIZE;
- workBuffer.buffer = RsaWorkBuffer;
- SESSMGR_MEM_ALLOC_BUFFER(LocalSignBuffer.buffer, TRUSTED_MEM, sizeof(UINT32), SignBuffer->length, TX_WAIT_FOREVER);
- SESSMGR_MEM_ALLOC_BUFFER(LocalMsgBuffer.buffer, TRUSTED_MEM, sizeof(UINT32), MsgBuffer->length, TX_WAIT_FOREVER);
- SESSMGR_MEMCPY_S(LocalSignBuffer.buffer, SignBuffer->length, SignBuffer->buffer, SignBuffer->length);
- LocalSignBuffer.length = SignBuffer->length;
- SESSMGR_MEMCPY_S(LocalMsgBuffer.buffer, MsgBuffer->length, MsgBuffer->buffer, MsgBuffer->length);
- LocalMsgBuffer.length = MsgBuffer->length;
- // Swap the Key and signature buffers. These are local buffers so no swapping back is necessary.
- SwapEndian(RsaKeyFromCert->e.buffer, RsaKeyFromCert->e.length);
- SwapEndian(RsaKeyFromCert->n.buffer, RsaKeyFromCert->n.length);
- SwapEndian(LocalSignBuffer.buffer, LocalSignBuffer.length);
- RsaVerifyParams.pMsgBuffer = (ROM_RSA_DATA_BUFFER*)&LocalMsgBuffer;
- RsaVerifyParams.pSignatureBuffer = (ROM_RSA_DATA_BUFFER*)&LocalSignBuffer;
- RsaVerifyParams.pbIsValid = &IsSignatureValid;
- RsaVerifyParams.CallbackAbortNow = NULL;
- RsaVerifyParams.pWorkBuffer = &workBuffer;
- RsaVerifyParams.HashFunc = (X509_sha1withRSAEncryption == IssuerInfo->AlgoType ? ROM_RSA_SCHEME_HASH_SHA1 : ROM_RSA_SCHEME_HASH_SHA256);
- Status = CryptoRsaPkcsVerify((RSA_IPP_KEY*)RsaKeyFromCert,
- FALSE,
- (RSA_VERIFY_PARAMS*)&RsaVerifyParams);
- if(LocalSignBuffer.buffer){
- SESSMGR_MEM_FREE(LocalSignBuffer.buffer)
- LocalSignBuffer.length = 0;
- }
- if(LocalMsgBuffer.buffer){
- SESSMGR_MEM_FREE(LocalMsgBuffer.buffer)
- LocalMsgBuffer.length = 0;
- }
- if ((Status != STATUS_SUCCESS) || (IsSignatureValid != TRUE)){
- DBG_ASSERT(0);
- return X509_INVALID_SIGNATURE;
- }
- #endif // #ifdef X509_FOR_PSE_PR
- break;
- default:
- assert(0);
- }
- }while(0);
- return Status;
- }
- #define CRYPTO_SIZE_SHA256 32
- #ifndef X509_FOR_PSE_PR
- STATUS VerifyOcspResponseAttributes(Uint8* OcspRespBuffer, SessMgrOcspResponseFields *ocspResponseFields, ISSUER_INFO* OcspCertRootPublicKey,
- SessMgrDataBuffer Nonce, OCSP_REQ_TYPE OcspReqType, BOOL UseFacsimileEpid)
- {
- SessMgrCertificateFields certificateFields;
- STATUS Status;
- UINT32 workBufferSize = 1000;
- UINT8 *workBuffer = NULL;
- ISSUER_INFO IssuerInfo;
- SessMgrDataBuffer PubKeyHashBuf;
- UINT8 HashOut[SHA1_HASH_LEN] = {0};
- PubKeyHashBuf.buffer = HashOut;
- PubKeyHashBuf.length = SHA1_HASH_LEN;
- if(ocspResponseFields->ocspResponseStatus != successful){
- return X509_STATUS_OCSP_FAILURE;
- }
- // parse the ocsp certificate
- SESSMGR_MEM_ALLOC_BUFFER(workBuffer, MM_DATA_HEAP_SHARED_RW, sizeof(UINT32), workBufferSize, TX_WAIT_FOREVER);
- do {
- Status = ParseCertificateChain(ocspResponseFields->responderCertificate.buffer,
- ocspResponseFields->responderCertificate.length,
- &certificateFields,
- workBuffer,
- workBufferSize,
- NULL,
- 0,
- NULL,
- OcspResponderCertificate,
- UseFacsimileEpid);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- break;
- }
- // verify OCSP response signature.
- IssuerInfo.AlgoType = ocspResponseFields->algorithmIdentifierForSignature;
- IssuerInfo.buffer = certificateFields.subjectPublicKey.buffer;
- IssuerInfo.length = certificateFields.subjectPublicKey.length;
- Status = VerifySignature(&IssuerInfo, &ocspResponseFields->tbsResponseData, &ocspResponseFields->signature, UseFacsimileEpid);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- Status = X509_INVALID_SIGNATURE;
- break;
- }
- // Verify Nonce only on Signed FW.
- #ifndef _WIN32_DEVPLATFORM
- #ifndef X509_FOR_PSE_PR
- if(!(gManifestDataPtr->ManifestHeader.manifestFlags.r.debugManifest)){
- #endif
- // Verify Nonce only for Non-cached Response.
- if(OcspReqType == NON_CACHED){
- // Make sure we have a nonce in the OCSP response
- if(!ocspResponseFields->nonce.buffer || Nonce.length <= 0){
- DBG_ASSERT(0);
- Status = X509_STATUS_OCSP_FAILURE;
- break;
- }
- if( memcmp(ocspResponseFields->nonce.buffer, Nonce.buffer, Nonce.length) != 0 || (ocspResponseFields->nonce.length != Nonce.length) )
- {
- DBG_ASSERT(0);
- Status = X509_STATUS_OCSP_FAILURE;
- break;
- }
- }
- #ifndef X509_FOR_PSE_PR
- }
- #endif
- #endif
- // If ResponderId is a KeyHash, then verify its a Hash of the responders public key.
- if(ocspResponseFields->ocspResponderIdKeyHash.buffer){
- Status = CryptoCreateHash(CRYPTO_HASH_TYPE_SHA1,
- &certificateFields.EncodedSubjectPublicKey,
- &PubKeyHashBuf,
- NULL,
- NULL,
- SINGLE_BLOCK);
- if(Status != STATUS_SUCCESS){
- DBG_ASSERT(0);
- Status = X509_STATUS_INTERNAL_ERROR;
- break;
- }
- if(SHA1_HASH_LEN != ocspResponseFields->ocspResponderIdKeyHash.length ||
- memcmp(HashOut,ocspResponseFields->ocspResponderIdKeyHash.buffer, ocspResponseFields->ocspResponderIdKeyHash.length) != 0){
- DBG_ASSERT(0);
- Status = X509_STATUS_OCSP_FAILURE;
- break;
- }
- }else{
- // If there is no Hash, There has to be a name. In the name structure, Common Name has to exist.
- if(!ocspResponseFields->ocspResponderIdName.commonName){
- DBG_ASSERT(0);
- Status = X509_STATUS_OCSP_FAILURE;
- break;
- }
- // if Responder Id is a Name, make sure the value matches the value in the certificate.
- if(ocspResponseFields->ocspResponderIdName.commonNameSize != certificateFields.subject.commonNameSize ||
- memcmp(ocspResponseFields->ocspResponderIdName.commonName, certificateFields.subject.commonName, certificateFields.subject.commonNameSize) != 0){
- DBG_ASSERT(0);
- Status = X509_STATUS_OCSP_FAILURE;
- break;
- }
- }
- // We have verified the OCSP response. See if we have trusted time. Else provision it.
- if(OcspReqType == NON_CACHED){
- Status = StoreTrustedTime(ocspResponseFields->producedAt);
- if(Status == STATUS_SUCCESS)
- gSessmgrCtx.TrustedTimeProvisioned = TRUE;
- }
- // If we have cached response, Make sure produced at was not more than a day
- if(OcspReqType == CACHED){
- Status = VerifyOcspCachedResponseValidity(ocspResponseFields);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- Status = X509_STATUS_OCSP_FAILURE;
- break;
- }
- }
- #ifdef PRINT
- printf("\nOcsp response signature verified ");
- SetConsoleTextAttribute(hConsole, 2);
- printf("\n \n *************** VerifyOcspResponseAttributes complete ***************** \n \n");
- SetConsoleTextAttribute(hConsole, 8);
- #endif
- Status = X509_STATUS_SUCCESS;
- } while(0);
- SESSMGR_MEM_FREE(workBuffer);
- return Status;
- }
- #endif // #ifndef X509_FOR_PSE_PR
- STATUS VerifyBasicCertificateAttributes(const Uint8* certificateDerEncoded, const Uint8* workBuffer, const SessMgrCertificateFields* certificateFields,
- const ISSUER_INFO *IssuerInfo, const CertificateType CertType, CertificateLevel CertLevel, BOOL UseFacsimileEpid)
- {
- SessMgrEcdsaPublicKey *EcdsaKey;
- #ifdef X509_FOR_PSE_PR
- UNUSED(certificateDerEncoded);
- UNUSED(workBuffer);
- UNUSED(EcdsaKey);
- UNUSED(CertType);
- UNUSED(CertLevel);
- UNUSED(UseFacsimileEpid);
- #endif
- // Make sure the signature Algorithms for issuer is the same as the one used in the TbsCertificate
- if(certificateFields->TbsCertSignAlgoId != certificateFields->algorithmIdentifierForSignature){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- #ifndef X509_FOR_PSE_PR //PSE Usage doesn't need to check Cert expiration
- STATUS Status = X509_GENERAL_ERROR;
- // Verify if the certificate time is valid. At this point we expect trusted time to be set.
- /* Chicken and Egg problem: we get trusted time from OCSP. How do we check validity of OCSP responder certificate?
- Solution : Intel signs the OCSP responder cert and EPID group certs. its valid for a really long time. So for these
- certs, dont check validity.*/
- if((CertType != EpidGroupCertificate) && (CertType != OcspResponderCertificate)){
- Status = VerifyValidity(certificateFields->notValidBeforeTime, certificateFields->notValidAfterTime);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_EXPIRED_CERTIFICATE;
- }
- }
- Status = VerifySignature(IssuerInfo, &certificateFields->messageBuffer, &certificateFields->signatureBuffer, UseFacsimileEpid);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_INVALID_SIGNATURE;
- }
- #endif
- // Common name and OrgName should be present.
- if(!certificateFields->issuer.commonName || !certificateFields->subject.commonName || !certificateFields->subject.organization){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- #if 0
- // The issuer of the root certificate has to be intel irrespective of the certificate type.
- if(CertLevel == root){
- if(certificateFields->issuer.commonNameSize != strlen("www.intel.com") ||
- memcmp(certificateFields->issuer.commonName, "www.intel.com", strlen("www.intel.com")) !=0){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- }
- #endif
- // Make sure the subject of the prev certificate is the issuer of the current certificate
- if(IssuerInfo->CommonNameBuf.buffer && IssuerInfo->CommonNameBuf.length > 0){
- if(certificateFields->issuer.commonNameSize != IssuerInfo->CommonNameBuf.length ||
- memcmp(certificateFields->issuer.commonName, IssuerInfo->CommonNameBuf.buffer, IssuerInfo->CommonNameBuf.length) != 0){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- }
- #ifndef X509_FOR_PSE_PR
- switch(CertType){
- case OcspResponderCertificate:
- if(certificateFields->keyUsage.value == 0){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- // Make sure only the non-repudiation and digitalSignature are set.
- if(certificateFields->keyUsage.value != (X509_BIT0 | X509_BIT1)){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- // ExtendedKeyUsage must be specified.
- if(certificateFields->ExtendedKeyUsage.value == 0){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- // Basic constraints extension should be present.
- if(!certificateFields->basicConstraint.isBasicConstraintPresent){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- // isCa should be deasserted. We will not delegate OCSP signing authority to anybody else.
- if(certificateFields->basicConstraint.isCa == DER_ENCODING_TRUE){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- break;
- case VerifierCertificate:
- // Basic Constraint should be present.
- if(!certificateFields->basicConstraint.isBasicConstraintPresent){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- // Make sure leaf certs dont have isCA set and intermediate Certs have isCa deasserted.
- if( (CertLevel == leaf && certificateFields->basicConstraint.isCa == DER_ENCODING_TRUE) ||
- (CertLevel != leaf && certificateFields->basicConstraint.isCa == DER_ENCODING_FALSE)){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- if(certificateFields->algorithmIdentifierForSubjectPublicKey == X509_ecdsaPublicKey){
- // For ECDSA public key, we expect curvve to be prime256v1
- EcdsaKey = (SessMgrEcdsaPublicKey *)certificateFields->subjectPublicKey.buffer;
- if(EcdsaKey->eccParameter != curvePrime256v1){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- }
- // For root and intermediate certificates, BIT5 (KeyCertSign) must be asserted
- if(CertLevel != leaf){
- if(certificateFields->keyUsage.value != X509_BIT5){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- }else{
- if(certificateFields->keyUsage.value != (X509_BIT0 | X509_BIT1)){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- }
- // Check for Subject Key Identifier. Per spec, all certificate except leaf should have this and should be equal to SHA1 of the public key.
- if(CertLevel != leaf){
- if(!certificateFields->SubjectKeyId.buffer || certificateFields->SubjectKeyId.length != SHA1_HASH_LEN ){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- if(VerifySha1Hash(&certificateFields->EncodedSubjectPublicKey, certificateFields->SubjectKeyId.buffer , certificateFields->SubjectKeyId.length) == FALSE){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- }
- // Every verifier cert should have an authority key id
- if(!certificateFields->AuthorityKeyId.buffer || (certificateFields->AuthorityKeyId.length != IssuerInfo->EncodedPublicKeyHashBuffer.length) ){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- // Verify Authority Key Id. Spec says Authority Key ID of current cert should be equal to the SubjectKeyId of the upper cert. SubjectKeyId is nothing but the hash of the upper certs public key.
- // we have that available in this function. So compare Authority Key with that.
- if(certificateFields->AuthorityKeyId.length != IssuerInfo->EncodedPublicKeyHashBuffer.length ||
- memcmp(certificateFields->AuthorityKeyId.buffer, IssuerInfo->EncodedPublicKeyHashBuffer.buffer, IssuerInfo->EncodedPublicKeyHashBuffer.length) != 0){
- // if the first cert is signed by the prod Intel IVK & GID is 0, try again with hash of the prod Intel IVK
- #ifndef X509_FOR_PSE_PR
- if (gSessmgrCtx.FuseGidZero){
- #endif
- UINT8 TempSignKeyBuffer[ECDSA_KEY_SIZE + 1] = {0};
- SessMgrDataBuffer TempDataBuffer = {sizeof(TempSignKeyBuffer), TempSignKeyBuffer};
- TempSignKeyBuffer[0] = 0x04;
- SESSMGR_MEMCPY_S(TempSignKeyBuffer + 1, ECDSA_KEY_SIZE, INTEL_ECDSA_PUBKEY_PROD_BE, sizeof(INTEL_ECDSA_PUBKEY_PROD_BE));
- Status = CryptoCreateHash(CRYPTO_HASH_TYPE_SHA1,
- &TempDataBuffer,
- &IssuerInfo->EncodedPublicKeyHashBuffer,
- NULL,
- NULL,
- SINGLE_BLOCK);
- if (Status != STATUS_SUCCESS) {
- DBG_ASSERT(0);
- return X509_STATUS_INTERNAL_ERROR;
- }
- if (certificateFields->AuthorityKeyId.length != IssuerInfo->EncodedPublicKeyHashBuffer.length ||
- memcmp(certificateFields->AuthorityKeyId.buffer, IssuerInfo->EncodedPublicKeyHashBuffer.buffer, IssuerInfo->EncodedPublicKeyHashBuffer.length) != 0){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- #ifndef X509_FOR_PSE_PR
- }
- else{
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- #endif // #ifdef X509_FOR_PSE_PR
- }
- // Product type must be present
- if(certificateFields->productType == invalidProductType || certificateFields->productType >= Max_ProductType){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- // If issuer certificate product type exists, ensure it matches current cert
- if ((IssuerInfo->productType != invalidProductType) && (IssuerInfo->productType != certificateFields->productType)) {
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- break;
- }
- #endif
- #ifdef PRINT
- SetConsoleTextAttribute(hConsole, 4);
- printf("\n \n *************** VerifyBasicCertificateAttributes complete ***************** \n \n");
- SetConsoleTextAttribute(hConsole, 8);
- #endif
- return X509_STATUS_SUCCESS;
- }
- #ifndef X509_FOR_PSE_PR
- static BOOL VerifySha1Hash(SessMgrDataBuffer *HashData, UINT8 *Expectedhash, UINT32 ExpectedHashLength)
- {
- UINT8 HashOut[SHA1_HASH_LEN] = {0};
- SessMgrDataBuffer HashBuf;
- STATUS Status;
- if(!HashData->buffer || HashData->length == 0)
- return FALSE;
- HashBuf.buffer = HashOut;
- HashBuf.length = SHA1_HASH_LEN;
- memset(HashBuf.buffer, 0 , HashBuf.length);
- Status = CryptoCreateHash(CRYPTO_HASH_TYPE_SHA1,
- HashData,
- &HashBuf,
- NULL,
- NULL,
- SINGLE_BLOCK);
- if(Status != STATUS_SUCCESS){
- DBG_ASSERT(0);
- return FALSE;
- }
- if(HashBuf.length != ExpectedHashLength ||
- memcmp(HashBuf.buffer, Expectedhash, ExpectedHashLength) != 0){
- return FALSE;
- }
- return TRUE;
- }
- #endif
- #ifndef X509_FOR_PSE_PR //NRG: not validating time in enclave
- STATUS VerifyValidity(SessMgrDateTime notValidBeforeTime, SessMgrDateTime NotValidAfterTime)
- {
- STATUS Status;
- NTP_TIMESTAMP CurrentTime, NotValidBefore, NotValidAfter;
- // At this point, we expect trusted time to be provisioned. Else Error
- if(!gSessmgrCtx.TrustedTimeProvisioned){
- DBG_ASSERT(0);
- return X509_STATUS_INTERNAL_ERROR;
- }
- Status = PrtcGetTime(&CurrentTime, gSessmgrCtx.TrustedTime.RtcOffset);
- if(Status != STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_INTERNAL_ERROR;
- }
- // extract time from the certs and convert it into NTP. Get NotValidBefore and NotValidAfter.
- // There is no day 0. We use that to find if the field has been populated. If not, ignore this check.
- if(notValidBeforeTime.date.yearMonthDay.day != 0){
- Status = ConvertTimeToNtp(notValidBeforeTime, &NotValidBefore);
- if(Status != STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_INTERNAL_ERROR;
- }
- if( CurrentTime.Seconds < NotValidBefore.Seconds - 120){
- DBG_ASSERT(0);
- return X509_STATUS_EXPIRED_CERTIFICATE;
- }
- }
- if(NotValidAfterTime.date.yearMonthDay.day != 0){
- Status = ConvertTimeToNtp(NotValidAfterTime, &NotValidAfter);
- if(Status != STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_INTERNAL_ERROR;
- }
- if(CurrentTime.Seconds > NotValidAfter.Seconds){
- DBG_ASSERT(0);
- return X509_STATUS_EXPIRED_CERTIFICATE;
- }
- }
- return X509_STATUS_SUCCESS;
- }
- STATUS VerifyOcspCachedResponseValidity(SessMgrOcspResponseFields *OcspResponseFields)
- {
- STATUS Status;
- NTP_TIMESTAMP CurrentTime = {0, 0};
- NTP_TIMESTAMP ProducedAt = {0, 0};
- // At this point, we expect trusted time to be provisioned. Else Error
- if(!gSessmgrCtx.TrustedTimeProvisioned){
- DBG_ASSERT(0);
- return X509_STATUS_INTERNAL_ERROR;
- }
- Status = PrtcGetTime(&CurrentTime, gSessmgrCtx.TrustedTime.RtcOffset);
- if(Status != STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_INTERNAL_ERROR;
- }
- // extract time from the certs and convert it into NTP. Get NotValidBefore and NotValidAfter
- Status = ConvertTimeToNtp(OcspResponseFields->producedAt, &ProducedAt);
- if(Status != STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_INTERNAL_ERROR;
- }
- #ifndef _WIN32_DEVPLATFORM // don't validate certificate time on DevPlatform
- // assuming no rollover
- if ((ProducedAt.Seconds > CurrentTime.Seconds) &&
- ((ProducedAt.Seconds - CurrentTime.Seconds) > OCSP_DELAY_TOLERANCE_SECONDS )){
- DBG_ASSERT(0);
- return X509_STATUS_INTERNAL_ERROR;
- }
- if ((CurrentTime.Seconds > ProducedAt.Seconds) &&
- ((CurrentTime.Seconds - ProducedAt.Seconds) > SECONDS_IN_DAY )){
- DBG_ASSERT(0);
- return X509_STATUS_EXPIRED_CERTIFICATE;
- }
- #endif // _WIN32_DEVPLATFORM
- return X509_STATUS_SUCCESS;
- }
- #endif // #ifndef X509_FOR_PSE_PR
- /*
- This function will parse the certificate, will extract out interesting data (defined in the "Fields" structure) and return them to the caller.
- */
- static STATUS sessMgrParseDerCert
- (
- IN X509_PROTOCOL* X509Protocol,
- IN Uint8* certificateDerEncoded,
- IN Uint8* pCertEnd,
- IN Uint8* workBuffer,
- IN UINT32 workBufferSize,
- OUT SessMgrCertificateFields* certificateFields,
- IN ISSUER_INFO *IssuerInfo,
- IN BOOL UseFacsimileEpid
- )
- {
- UINT32 Status;
- /* Refer to certificate structure for definition */
- Uint8* workBufferStart = workBuffer;
- UINT8* current_ptr = certificateDerEncoded;
- UINT8* pTemp;
- UINT32 length;
- UINT32 i = 0;
- SessMgrEllipticCurveParameter params = unknownParameter;
- UINT8 EncodingBytes;
- UINT32 padding;
- #ifdef PRINT
- printf("\n **************** Parsing a Certificate ******************** ");
- for(i=0;i<certificateFields->serialNumber.length;i++)
- printf("%hhx ",*(certificateFields->serialNumber.buffer + i));
- #endif
- #ifdef X509_FOR_PSE_PR
- UNUSED(X509Protocol);
- UNUSED(i);
- #endif
- do{
- Status = ParseIdAndLength(¤t_ptr, pCertEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- certificateFields->messageBuffer.buffer = current_ptr;
- /* Start of TBS Certificate : Starts with a sequence */
- Status = ParseIdAndLength(¤t_ptr, pCertEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- // Total signed buffer length = certificate Length + Encoding Bytes ( +1 is for the Type identifier)
- certificateFields->messageBuffer.length = length + EncodingBytes + 1;
- /*** Early Signature Verification ****/
- // Try to verify signature first. That way we resolve all corruption problems.
- pTemp = certificateFields->messageBuffer.buffer + certificateFields->messageBuffer.length;
- // Current pointer is at SignatureAlgorithm which is a algorithm identifier
- Status = ParseAlgoIdentifier(&pTemp, pCertEnd, (UINT32*)&certificateFields->TbsCertSignAlgoId, signature_algo, ¶ms);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- break;
- }
- // Next field : SignatureValue
- Status = ParseSignatureValue(&pTemp, pCertEnd, &workBuffer, workBufferSize - (int)(workBuffer-workBufferStart), &certificateFields->signatureBuffer, certificateFields->TbsCertSignAlgoId);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- break;
- }
- Status = VerifySignature(IssuerInfo, &certificateFields->messageBuffer, &certificateFields->signatureBuffer, UseFacsimileEpid);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_INVALID_SIGNATURE;
- }
- //
- // if signature verifies, then length values in cert
- // are ok wrt Spectre
- //
- sgx_lfence();
- /**** End Early Signature Verification *****/
- // Next Field : Version (Optional field with explicit tagging)
- Status = ParseIdAndLength(¤t_ptr, pCertEnd, EXPLICIT_TAG_0_ID_VALUE, &length, &EncodingBytes, TRUE);
- if( (Status != X509_STATUS_SUCCESS) && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status != X509_STATUS_NOT_FOUND){
- // We have a version number. Note: Not using ParseInteger function because certificateVersion is defined as a UINT32 and not a DataBuffer
- Status = ParseIdAndLength(¤t_ptr, pCertEnd, DER_ENCODING_INTEGER_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS || length > MAX_VERSION_LENGTH_SIZE_BYTES){
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- SESSMGR_MEMCPY_S((UINT8*)&certificateFields->certificateVersion + sizeof(UINT32) - length, length, current_ptr, length);
- // The certificates are big endian.
- SwapEndian((UINT8 *)&certificateFields->certificateVersion, sizeof(UINT32));
- if(certificateFields->certificateVersion != v3){
- Status = X509_STATUS_INVALID_VERSION;
- break;
- }
- current_ptr+= length;
- }else{
- /* Default is v1 according to spec . But we dont support onyl v3. Return error. */
- Status = X509_STATUS_INVALID_VERSION;
- break;
- }
- // Next Field : Certificate Serial Number Format : Integer Identifier + Length + Value (Max 20 bytes)
- Status = ParseInteger(¤t_ptr, pCertEnd, &certificateFields->serialNumber, FALSE, TRUE, &padding);
- if ((Status != X509_STATUS_SUCCESS) || (certificateFields->serialNumber.length + padding > MAX_HASH_LEN)) {
- DBG_ASSERT(0);
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- #ifdef PRINT
- printf("\n Serial Number ");
- for(i=0;i<certificateFields->serialNumber.length;i++)
- printf("%hhx ",*(certificateFields->serialNumber.buffer + i));
- #endif
- // Next Field : Algorithm Identifier (signature) The OID is expected to be one of the HardCodedSignatureAlgorithmOid array values.
- Status = ParseAlgoIdentifier(¤t_ptr, pCertEnd, (UINT32*)&certificateFields->algorithmIdentifierForSignature,signature_algo, ¶ms);
- if(Status != X509_STATUS_SUCCESS){
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- // Next Field : issuer
- Status = ParseName(¤t_ptr, pCertEnd, &certificateFields->issuer);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- break;
- }
- // Next Field : Validity Format : sequence notBefore notAfter
- Status = ParseIdAndLength(¤t_ptr, pCertEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- // Parse notBefore, notAfter, Subject, SubjectPublic key info
- Status = ParseTime(¤t_ptr, pCertEnd, &certificateFields->notValidBeforeTime);
- if(Status != X509_STATUS_SUCCESS)
- break;
- Status = ParseTime(¤t_ptr, pCertEnd, &certificateFields->notValidAfterTime);
- if(Status != X509_STATUS_SUCCESS)
- break;
- Status = ParseName(¤t_ptr, pCertEnd, &certificateFields->subject);
- if(Status != X509_STATUS_SUCCESS)
- break;
- Status = ParseSubjectPublicKeyInfo(¤t_ptr, pCertEnd, &workBuffer, certificateFields);
- if(Status != X509_STATUS_SUCCESS)
- break;
- // Next Field: IssuerUniqueId [optional] Implicit TAG Number is 1 Type : UniqueIdentifier (BIT STRING)
- Status = ParseIdAndLength(¤t_ptr, pCertEnd, IMPLICIT_TAG_ID + TAG_NUMBER_ISSUER_UNIQUE_ID, &length, &EncodingBytes, TRUE);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status != X509_STATUS_NOT_FOUND){
- certificateFields->IssuerUniqueId.buffer = current_ptr;
- certificateFields->IssuerUniqueId.length = length;
- current_ptr += length;
- }
- // Next Field: SubjectUniqueId [optional] Implicit TAG Number is 2 Type : UniqueIdentifier (BIT STRING)
- Status = ParseIdAndLength(¤t_ptr, pCertEnd, IMPLICIT_TAG_ID + TAG_NUMBER_SUBJECT_UNIQUE_ID, &length, &EncodingBytes, TRUE);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status != X509_STATUS_NOT_FOUND){
- certificateFields->SubjectUniqueId.buffer = current_ptr;
- certificateFields->SubjectUniqueId.length = length;
- current_ptr += length;
- }
- // Next Field: Extensions [optional]
- Status = ParseIdAndLength(¤t_ptr, pCertEnd, EXPLICIT_TAG_ID + TAG_NUMBER_EXTENSIONS, &length, &EncodingBytes, TRUE);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status != X509_STATUS_NOT_FOUND){
- #ifndef X509_FOR_PSE_PR
- Status = ParseCertExtensions(¤t_ptr, current_ptr + length, certificateFields);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- break;
- }
- #else
- current_ptr += length;
- #endif
- }
- /* End of TbsCErtificate */
- // Current pointer is at SignatureAlgorithm which is a algorithm identifier
- Status = ParseAlgoIdentifier(¤t_ptr, pCertEnd, (UINT32*)&certificateFields->TbsCertSignAlgoId, signature_algo, ¶ms);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- break;
- }
- // Next field : SignatureValue
- Status = ParseSignatureValue(¤t_ptr, pCertEnd, &workBuffer, workBufferSize - (int)(workBuffer - workBufferStart), &certificateFields->signatureBuffer, certificateFields->algorithmIdentifierForSignature);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- break;
- }
- }while(0);
- DBG_ASSERT((int)(workBuffer - workBufferStart) < workBufferSize)
- DBG_ASSERT(Status == X509_STATUS_SUCCESS);
- if (current_ptr != pCertEnd) {
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- return Status;
- }
- #ifndef X509_FOR_PSE_PR
- STATUS sessMgrParseOcspResponse
- (
- IN X509_PROTOCOL* X509Protocol,
- IN Uint8* OcspResponse,
- IN Uint8* OcspResponseEnd,
- IN Uint8* workBuffer,
- IN UINT32 workBufferSize,
- OUT SessMgrOcspResponseFields* OcspResponseFields
- )
- {
- STATUS Status;
- Uint8* workBufferStart = workBuffer;
- UINT8* current_ptr = OcspResponse;
- UINT32 length;
- UINT32 temp;
- SessMgrOcspSingleResponse *SingleResponse;
- UINT8 *end_of_single_responses;
- SessMgrEllipticCurveParameter params;
- UINT8 EncodingBytes;
- UINT32 padding;
- /* Ocsp response is a SEQ { responseStatus, response bytes }*/
- do{
- Status = ParseIdAndLength(¤t_ptr, OcspResponseEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- // Next Field: response status response status is a enumerated type
- Status = ParseIdAndLength(¤t_ptr, OcspResponseEnd, DER_ENCODING_ENUMERATED_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS || length != 1){
- // Note: currently we support only 7 bits. So error out if length is more than 1 byte
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- OcspResponseFields->ocspResponseStatus = (ResponseStatus)*current_ptr;
- current_ptr += length;
- // Next Field: response bytes Reponsne Bytes is a SEQ { response type , response }. response bytes is optional
- Status = ParseIdAndLength(¤t_ptr, OcspResponseEnd, EXPLICIT_TAG_ID + TAG_NUMBER_RESPONSE_BYTES, &length, &EncodingBytes, TRUE);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status == X509_STATUS_NOT_FOUND){
- // No response bytes. Nothing more to parse.
- Status = X509_STATUS_SUCCESS;
- break;
- }
- /* WE HAVE A RESPONSE !!!! */
- Status = ParseIdAndLength(¤t_ptr, OcspResponseEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- // Next Field: responseType Type : Object ID
- Status = ParseOID(¤t_ptr, OcspResponseEnd, &temp, &OcspResponseTypeOid[0][0],
- sizeof(OcspResponseTypeOid)/sizeof(OcspResponseTypeOid[0]),
- sizeof(OcspResponseTypeOid[0]));
- if(Status != X509_STATUS_SUCCESS || temp != 0){
- DBG_ASSERT(0);
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- // Next Field: response Type : OCTET STRING
- Status = ParseIdAndLength(¤t_ptr, OcspResponseEnd, DER_ENCODING_OCTET_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- // The only response type we support is basicOcspResponse. BasicOcspResponse is SEQ {tbsResponseData, SignatureAlgo, Signature, Certs [optional] }
- Status = ParseIdAndLength(¤t_ptr, OcspResponseEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- // Next Field : tbsResponseData Format : Seq { version [optional], ResponderId, ProducesdAt, responses, responseExtensions [optional]
- OcspResponseFields->tbsResponseData.buffer = current_ptr;
- Status = ParseIdAndLength(¤t_ptr, OcspResponseEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- OcspResponseFields->tbsResponseData.length = length + EncodingBytes + 1;
- // We dont store the version anywhere. Just parse if present and move pointer to next type
- Status = ParseIdAndLength(¤t_ptr, OcspResponseEnd, EXPLICIT_TAG_ID + TAG_NUMBER_VERSION, &length, &EncodingBytes, TRUE);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status != X509_STATUS_NOT_FOUND){
- // we have version. Just parse over it
- current_ptr += length;
- }
- // Next Field : ResponderId ResponderId can be a choice of either Name or KeyHash. We distinguish them using the tags
- Status = ParseIdAndLength(¤t_ptr, OcspResponseEnd, EXPLICIT_TAG_ID + TAG_NUMBER_RESPONDER_NAME, &length, &EncodingBytes, TRUE);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status != X509_STATUS_NOT_FOUND){
- Status = ParseName(¤t_ptr, OcspResponseEnd, &OcspResponseFields->ocspResponderIdName);
- if(Status != X509_STATUS_SUCCESS)
- break;
- }else{
- Status = ParseIdAndLength(¤t_ptr, OcspResponseEnd, EXPLICIT_TAG_ID + TAG_NUMBER_RESPONDER_KEYHASH, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS){
- /* We either need to have a Id or a Keyhash */
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- // KeyHash is a octet String
- Status = ParseIdAndLength(¤t_ptr, OcspResponseEnd, DER_ENCODING_OCTET_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- OcspResponseFields->ocspResponderIdKeyHash.buffer = current_ptr;
- OcspResponseFields->ocspResponderIdKeyHash.length = length;
- current_ptr +=length;
- }
- /* Next Field : ProducedAt */
- Status = ParseTime(¤t_ptr, OcspResponseEnd, &OcspResponseFields->producedAt);
- if(Status != X509_STATUS_SUCCESS)
- break;
- #ifdef TIME_PRINT
- printf("\n Produced At ");
- PrintValidity(&OcspResponseFields->producedAt);
- #endif
- // Next Field : response Format : responses is a SEQ { single Responses }
- Status = ParseIdAndLength(¤t_ptr, OcspResponseEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- end_of_single_responses = current_ptr + length;
- // Each single response is parsed and put into the SessMgrOcspSingleResponse structure. This structure is declared out of the work buffer
- SingleResponse = (SessMgrOcspSingleResponse *)workBuffer;
- OcspResponseFields->allResponses = (SessMgrOcspSingleResponse*) workBuffer;
- OcspResponseFields->numberOfSingleReponses = 0;
- while(current_ptr < end_of_single_responses){
- // update workbuffer pointer for future use
- workBuffer += sizeof(SessMgrOcspSingleResponse);
- // Each single response is a SEQ { CertID, CertStatus, Thisupdate, nextUpdate [optional], SingleExtensions [optional] */
- Status = ParseIdAndLength(¤t_ptr, end_of_single_responses, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- // current pointer is over CertId CertId is a Seq {hash algorithm, issuername hash, issuerKeyHash, serialNumber}
- Status = ParseIdAndLength(¤t_ptr, end_of_single_responses, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- // current pointer over Hash algo Hash algorithm is a Algorithm identifier
- Status = ParseAlgoIdentifier(¤t_ptr, end_of_single_responses, (UINT32*)&SingleResponse->issuerIdentifierHashType,Hash_algo, ¶ms);
- if(Status != X509_STATUS_SUCCESS)
- break;
- // Next Field: IssueNameHash Type : octet string */
- Status = ParseIdAndLength(¤t_ptr, end_of_single_responses, DER_ENCODING_OCTET_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- SingleResponse->issuerNameHash.buffer = current_ptr;
- SingleResponse->issuerNameHash.length = length;
- current_ptr+=length;
- // Next Field: IssueKeyHash Type : octet string
- Status = ParseIdAndLength(¤t_ptr, end_of_single_responses, DER_ENCODING_OCTET_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- SingleResponse->issuerKeyHash.buffer = current_ptr;
- SingleResponse->issuerKeyHash.length = length;
- current_ptr+=length;
- // Next Field: SerialNumber Type : Integer */
- Status = ParseInteger(¤t_ptr, end_of_single_responses, &SingleResponse->serialNumber, FALSE, TRUE, &padding);
- if(Status != X509_STATUS_SUCCESS || (SingleResponse->serialNumber.length + padding > MAX_HASH_LEN)){
- DBG_ASSERT(0);
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- // Next field: CertStatus certStatus can be a choice of { good [type : NULL], revoked [type : revoked info], unknown [type : NULL]
- switch(*current_ptr)
- {
- case IMPLICIT_TAG_ID + TAG_NUMBER_GOOD:
- SingleResponse->ocspCertificateStatus = good;
- current_ptr++;
- /* NULL id is always followed by length 0x00 */
- if(*current_ptr != 0)
- {
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- current_ptr++;
- break;
- case IMPLICIT_TAG_ID + TAG_NUMBER_UNKNOWN:
- SingleResponse->ocspCertificateStatus = unknown;
- current_ptr++;
- /* NULL id is always followed by length 0x00 */
- if(*current_ptr != 0)
- {
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- current_ptr++;
- break;
- case IMPLICIT_TAG_STRUCTURED_TYPE_ID + TAG_NUMBER_REVOKED:
- SingleResponse->ocspCertificateStatus = revoked;
- /* This will be followed by a revoked time and reason.
- We parse but ignore those fields
- */
- current_ptr++;
- /* Get length */
- Status = DecodeLength(current_ptr, end_of_single_responses, &length, &EncodingBytes);
- if(Status != X509_STATUS_SUCCESS)
- break;
- current_ptr += EncodingBytes;
- /* Move current_ptr beyond the revoked data */
- current_ptr +=length;
- break;
- default:
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- if(Status != X509_STATUS_SUCCESS)
- break;
- // Next Field : ThisUpdate type: GeneralizedTime
- Status = ParseTime(¤t_ptr, end_of_single_responses, &SingleResponse->thisUpdate);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* Next Field : NextUpdate [optional] */
- Status = ParseIdAndLength(¤t_ptr, end_of_single_responses, EXPLICIT_TAG_ID + TAG_NUMBER_NEXT_UPDATE, &length, &EncodingBytes, TRUE);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status != X509_STATUS_NOT_FOUND){
- Status = ParseTime(¤t_ptr, end_of_single_responses, &SingleResponse->nextUpdate);
- if(Status != X509_STATUS_SUCCESS)
- break;
- }
- /* INTERESTING CASE: Both singleExtensions and responseExtensions use the tag [1]. So at this point, there is no way of finding out if "A1" means Single or response Extentions.
- We check the end of sequence pointer to resolve this.
- */
- if(current_ptr < end_of_single_responses){
- // Next Field : Single Extensions [optional] we parse this but ignore the contents
- Status = ParseIdAndLength(¤t_ptr, end_of_single_responses, EXPLICIT_TAG_ID + TAG_NUMBER_SINGLE_EXTENSIONS, &length, &EncodingBytes, TRUE);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status != X509_STATUS_NOT_FOUND){
- /* Move pointer past the extensions */
- current_ptr +=length;
- }
- }
- SingleResponse = (SessMgrOcspSingleResponse *)((UINT8 *)SingleResponse + sizeof(SessMgrOcspSingleResponse));
- OcspResponseFields->numberOfSingleReponses++;
- Status = X509_STATUS_SUCCESS;
- }
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- #ifdef PRINT
- int i;
- printf("\n Number of single responses %d", OcspResponseFields->numberOfSingleReponses);
- for (i=0;i<OcspResponseFields->numberOfSingleReponses;i++){
- printf("\n\n Response Number %d", i);
- SingleResponse = (SessMgrOcspSingleResponse *)(OcspResponseFields->allResponses) + i;
- printf("\n serial number ");
- PrintDataBuffer(&SingleResponse->serialNumber);
- #ifdef TIME_PRINT
- printf("\n This Update ");
- PrintValidity(&SingleResponse->thisUpdate);
- #endif
- }
- #endif
- // Next Field : Response Extensions [optional]
- Status = ParseIdAndLength(¤t_ptr, OcspResponseEnd, EXPLICIT_TAG_ID + TAG_NUMBER_RESPONSE_EXTENSIONS, &length, &EncodingBytes, TRUE);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status != X509_STATUS_NOT_FOUND){
- // Move pointer past the extensions
- Status = ParseOcspExtensions(¤t_ptr, current_ptr + length, OcspResponseFields);
- if(Status != X509_STATUS_SUCCESS){
- break;
- }
- }
- // Next field : Signature Algorithm Id*/
- Status = ParseAlgoIdentifier(¤t_ptr, OcspResponseEnd, (UINT32 *)&OcspResponseFields->algorithmIdentifierForSignature ,signature_algo, ¶ms);
- if(Status != X509_STATUS_SUCCESS)
- break;
- Status = ParseSignatureValue(¤t_ptr, OcspResponseEnd, &workBuffer, workBufferSize - (int)(workBuffer - workBufferStart), &OcspResponseFields->signature, OcspResponseFields->algorithmIdentifierForSignature);
- if(Status != X509_STATUS_SUCCESS)
- break;
- // Next field : Certificate of the OCSP responder. This can be a chain */
- // ??? why is this optional
- Status = ParseIdAndLength(¤t_ptr, OcspResponseEnd, EXPLICIT_TAG_ID + TAG_NUMBER_CERTS, &length, &EncodingBytes, TRUE);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status != X509_STATUS_NOT_FOUND){
- /* This is a sequence of certificates. */
- Status = ParseIdAndLength(¤t_ptr, OcspResponseEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- OcspResponseFields->responderCertificate.buffer = current_ptr;
- OcspResponseFields->responderCertificate.length = length;
- current_ptr += length;
- }
- }while(0);
- DBG_ASSERT(Status == X509_STATUS_SUCCESS);
- if (current_ptr != OcspResponseEnd) {
- DBG_ASSERT(0)
- return X509_STATUS_ENCODING_ERROR;
- }
- return Status;
- }
- #endif
- /* Common functions */
- #ifndef X509_FOR_PSE_PR
- static STATUS ParseBoolean(UINT8 **ppCurrent, UINT8 *pEnd, BOOL* Value, BOOL optional)
- {
- STATUS Status;
- UINT8 *current_ptr = *ppCurrent;
- UINT8 EncodingBytes;
- UINT32 length;
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_BOOLEAN_ID, &length, &EncodingBytes, optional);
- if(Status == X509_STATUS_NOT_FOUND && optional == TRUE)
- return X509_STATUS_NOT_FOUND;
- if(Status != X509_STATUS_SUCCESS || length != 1){
- Status = X509_STATUS_ENCODING_ERROR;
- return Status;
- }
- *Value = *current_ptr;
- current_ptr++;
- /* we expect Status to be 0xFF or 0x00 */
- if( (*Value != DER_ENCODING_TRUE) && (*Value != DER_ENCODING_FALSE))
- return X509_STATUS_ENCODING_ERROR;
- *ppCurrent = current_ptr;
- return X509_STATUS_SUCCESS;
- }
- #endif
- /* ParseInteger will strip out the integer encoding part. If parsing is successful, ParseInteger
- will update the current pointer and length
- Returns X509_ENCODING_ERROR on failure
- */
- static STATUS ParseInteger(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrDataBuffer* DataBuf, BOOL isOptional, BOOL MustBePositive, UINT32 *PaddingLen)
- {
- STATUS Status;
- UINT8 *current_ptr = *ppCurrent;
- UINT32 Integer_Length;
- UINT8 EncodingBytes;
- UINT32 PaddingCounter = 0;
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_INTEGER_ID, &Integer_Length, &EncodingBytes, isOptional);
- if(isOptional == TRUE && Status == X509_STATUS_NOT_FOUND)
- return X509_STATUS_NOT_FOUND;
- if(Status != X509_STATUS_SUCCESS)
- return X509_STATUS_ENCODING_ERROR;
- // MSB must be zero for positive integer. Error if MSB is not zero and we expect positive
- //
- // current_ptr could be out of bounds (speculatively)
- //
- sgx_lfence();
- if(MustBePositive && (*current_ptr & 0x80))
- return X509_STATUS_ENCODING_ERROR;
- // Note : DER Integer Encoding adds 0x00 if MSB of the actual integer is one. Ignore the first byte if it is 0x00
- if ((*current_ptr == 0) && (Integer_Length > 1)){
- current_ptr++; // skip padding
- Integer_Length--; // remove padding from length
- PaddingCounter++;
- }
- DataBuf->buffer = current_ptr;
- DataBuf->length = Integer_Length;
- *ppCurrent = current_ptr + Integer_Length;
- if (PaddingLen)
- *PaddingLen = PaddingCounter;
- return X509_STATUS_SUCCESS;
- }
- #ifndef X509_FOR_PSE_PR
- STATUS ParseOcspExtensions(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrOcspResponseFields* OcspResponseFields)
- {
- UINT8 *current_ptr = *ppCurrent;
- UINT32 ExtensionType;
- BOOL critical;
- UINT32 length;
- STATUS Status;
- UINT8 EncodingBytes;
- do{
- // Extensions = SEQ { extension } Each extension is associated with a Object ID. We support the extensions listed in ExtensionOID array.
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- while(current_ptr < pEnd){
- // Each extension is a SEQ { extid (OID) , critical (BOOLEAN), extnValue (OCTET STRING) }
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* Next Field : Extension OID */
- Status = ParseOID(¤t_ptr, pEnd, &ExtensionType, &OcspExtensionOid[0][0],
- sizeof(OcspExtensionOid)/sizeof(OcspExtensionOid[0]),
- sizeof(OcspExtensionOid[0]));
- // Note : We might have unsupported extensions.
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_UNKNOWN_OID){
- DBG_ASSERT(0);
- break;
- }
- // Next field is "Critical". This indicates whether it is mandatory for the parser to understand the extension. This is an optinal field. default is false
- Status = ParseBoolean(¤t_ptr, pEnd, &critical, TRUE);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status == X509_STATUS_NOT_FOUND)
- critical = DER_ENCODING_FALSE;
- // Next Field: Extn Value This is a OCTET STRING
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_OCTET_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- switch(ExtensionType)
- {
- case Nonce:
- // Some OCSP responders have an additional encoding of OCTET string for the nonce.
- // We know the Nonce is 32 bytes (Per Sigma Spec. If given length is more than that, then check if this extra encoding was included.
- if(length > SIGMA_NONCE_LENGTH){
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_OCTET_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- }
- DBG_ASSERT(length == SIGMA_NONCE_LENGTH);
- OcspResponseFields->nonce.buffer = current_ptr;
- OcspResponseFields->nonce.length = length;
- current_ptr+=length;
- break;
- default:
- /* unsupported extension.
- Check if it marked as critical. If so, return error else ignore this extension
- */
- if(critical == DER_ENCODING_TRUE){
- DBG_ASSERT(0);
- Status = X509_STATUS_UNSUPPORTED_CRITICAL_EXTENSION;
- break;
- }
- else{
- /* Extension is non-criticial. So it is ok if we dont support it .
- Move current pointer to the next extension */
- current_ptr += length;
- continue;
- }
- } // switch
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- break;
- }
- Status = X509_STATUS_SUCCESS;
- } // WHILE end of extensions
- }while(0); // do_while
- *ppCurrent = current_ptr;
- return Status;
- }
- #endif
- #ifndef X509_FOR_PSE_PR
- STATUS ParseCertExtensions(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrCertificateFields* certificateFields)
- {
- UINT8 *current_ptr = *ppCurrent;
- UINT32 ExtensionType;
- BOOL critical;
- UINT32 length;
- STATUS Status;
- TAG_TYPE TagType;
- UINT8 EncodingBytes;
- UINT8 PaddedBits;
- SessMgrDataBuffer DataBuf;
- UINT32 ExtendedKeyUsageOcspType;
- do{
- // Extensions = SEQ { extension } Each extension is associated with a Object ID. We support the extensions listed in ExtensionOID array.
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- while(current_ptr < pEnd){
- // Each extension is a SEQ { extid (OID) , critical (BOOLEAN), extnValue (OCTET STRING) }
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* Next Field : Extension OID */
- Status = ParseOID(¤t_ptr, pEnd, &ExtensionType, &CertExtensionOid[0][0],
- sizeof(CertExtensionOid)/sizeof(CertExtensionOid[0]),
- sizeof(CertExtensionOid[0]));
- // Note : We might have unsupported extensions.
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_UNKNOWN_OID){
- DBG_ASSERT(0);
- break;
- }
- // Next field is "Critical". This indicates whether it is mandatory for the parser to understand the extension. This is an optinal field. default is false
- Status = ParseBoolean(¤t_ptr, pEnd, &critical, TRUE);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status == X509_STATUS_NOT_FOUND)
- critical = DER_ENCODING_FALSE;
- // Next Field: Extn Value This is a OCTET STRING
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_OCTET_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- switch(ExtensionType)
- {
- case AuthorityKeyId:
- /* Authority ID is a SEQ of {KeyIdentifier [optional TAG 0] , General Names [optional Tag 1], Certificate Serial number [optional Tag 2] */
- /* Currently supported Intel and CA certs have general names and Certificate serial numbers as NULL */
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* See if optional arguments are present */
- // Note: InvalidTag means either the tag was not found (not an error if the field is optional) or the tag was not recognized.
- FIND_TAG_TYPE(current_ptr, TAG_NUMBER_AUTHORITY_KEY_ID, TagType);
- if(TagType != invalid_tag){
- /* We have an implicit or explicit tag */
- current_ptr++;
- /* Get Length of sequence */
- Status = DecodeLength(current_ptr, pEnd, &length, &EncodingBytes);
- if(Status != X509_STATUS_SUCCESS)
- break;
- current_ptr += EncodingBytes;
- if(TagType == explicit_tag){
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_OCTET_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- }
- /* Store the Authority Key ID into the data buffer */
- certificateFields->AuthorityKeyId.buffer = current_ptr;
- certificateFields->AuthorityKeyId.length = length;
- current_ptr+=length;
- }
- FIND_TAG_TYPE(current_ptr, TAG_NUMBER_AUTHORITY_CERT_ISSUER_ID, TagType);
- if(TagType != invalid_tag){
- current_ptr++;
- Status = DecodeLength(current_ptr, pEnd, &length, &EncodingBytes);
- if(Status != X509_STATUS_SUCCESS)
- break;
- current_ptr += EncodingBytes;
- if(TagType == explicit_tag){
- /* Expecting a NULL. Encoding for NULL is 0x05 0x00 */
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_NULL_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS || length !=0)
- break;
- }
- }
- FIND_TAG_TYPE(current_ptr, TAG_NUMBER_AUTHORITY_CERT_SERIAL_NUMBER_ID, TagType);
- if(TagType != invalid_tag){
- current_ptr++;
- Status = DecodeLength(current_ptr, pEnd, &length, &EncodingBytes);
- if(Status != X509_STATUS_SUCCESS)
- break;
- current_ptr += EncodingBytes;
- if(TagType == explicit_tag){
- /* Expecting a NULL. Encoding for NULL is 0x05 0x00 */
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_NULL_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS || length !=0)
- break;
- }
- }
- break;
- case SubjectKeyId:
- // Next Field: Extn Value This is a OCTET STRING
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_OCTET_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* Store the Subject Key ID into the data buffer */
- certificateFields->SubjectKeyId.buffer = current_ptr;
- certificateFields->SubjectKeyId.length = length;
- current_ptr+=length;
- break;
- case KeyUsage:
- /* KeyUsage is a bit string */
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_BIT_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* KeyUsage is defined as a 16 bit value.So we expect the length to be 1 or 2. Add 1 to the check to account for the byte containing the number of bits paddd */
- if(length != 2 && length != 3){
- DBG_ASSERT(0);
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- /* current_ptr is pointing to the padded bits */
- PaddedBits = *current_ptr;
- current_ptr++;
- /* decrementing length by one because length included the padded bits octet that we have already parsed*/
- length--;
- if(length == 2){
- certificateFields->keyUsage.value = *current_ptr;
- /* Shift by 8 */
- certificateFields->keyUsage.value = certificateFields->keyUsage.value << 8;
- current_ptr++;
- }
- certificateFields->keyUsage.value = *current_ptr;
- current_ptr++;
- break;
- case ExtendedKeyUsage:
- /* ExtendedKeyUsage is a sequence of KeyPurposeId's */
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- // KeyPurposeId is a object identifier
- Status = ParseOID(¤t_ptr, pEnd, &ExtendedKeyUsageOcspType, &ExtendedKeyUsageOcspSignOid[0][0],
- sizeof(ExtendedKeyUsageOcspSignOid)/sizeof(ExtendedKeyUsageOcspSignOid[0]),
- sizeof(ExtendedKeyUsageOcspSignOid[0]));
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* we only support OcspSign in Extended key usage */
- if(ExtendedKeyUsageOcspType != 0){
- DBG_ASSERT(0);
- Status = X509_STATUS_UNSUPPORTED_TYPE;
- break;
- }else{
- certificateFields->ExtendedKeyUsage.usage.OCSPSign = 1;
- }
- break;
- case BasicConstraint:
- /* Basic constraint is a SEQ { BOOLEAN (default false) , Integer [optional] */
- certificateFields->basicConstraint.isBasicConstraintPresent = TRUE;
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* Next is a optional field for boolean */
- Status = ParseBoolean(¤t_ptr, pEnd, &certificateFields->basicConstraint.isCa, TRUE);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status == X509_STATUS_NOT_FOUND)
- certificateFields->basicConstraint.isCa = DER_ENCODING_FALSE;
- // Next field is PathLenConstraint [Integer optional]
- Status = ParseInteger(¤t_ptr, pEnd, &DataBuf, TRUE, FALSE, NULL);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND )
- break;
- if(Status == X509_STATUS_NOT_FOUND)
- certificateFields->basicConstraint.pathLenConstraint = 0xFF;
- else{
- Status = swapendian_memcpy((UINT8 *)&certificateFields->basicConstraint.pathLenConstraint,
- sizeof(UINT32),
- DataBuf.buffer, DataBuf.length);
- if(Status != X509_STATUS_SUCCESS)
- break;
- }
- Status = X509_STATUS_SUCCESS;
- break;
- case CertificatePolicy:
- Status = ParseCertificatePolicy(¤t_ptr, pEnd, &certificateFields->CertificatePolicy);
- break;
- case ProductType:
- /* Product type is a enumerated type */
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_ENUMERATED_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS || length != 1)
- {
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- certificateFields->productType = (SessMgrProductType)*current_ptr;
- current_ptr++;
- break;
- default:
- /* unsupported extension.
- Check if it marked as critical. If so, return error else ignore this extension
- */
- if(critical == DER_ENCODING_TRUE){
- DBG_ASSERT(0);
- Status = X509_STATUS_UNSUPPORTED_CRITICAL_EXTENSION;
- break;
- }
- else{
- /* Extension is non-criticial. So it is ok if we dont support it .
- Move current pointer to the next extension */
- current_ptr += length;
- continue;
- }
- } // switch
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- break;
- }
- Status = X509_STATUS_SUCCESS;
- } // WHILE end of extensions
- }while(0);
- DBG_ASSERT(Status == X509_STATUS_SUCCESS);
- *ppCurrent = current_ptr;
- return Status;
- }
- /* Certificate Policy is a SEQ of Policy Information.
- Policy information is Seq of {Policy Identifier, Policy Qualifier [optional] }
- Policy Identifier is a Object ID
- Policy Qualifier Info is Seq {PolicyqualifierId, qualifier }
- PolicyqualifierId is a known Object id
- Qualifier is a CHOICE{cPSuri, UserNotice}
- we only support cpSuri which is a IA5string
- */
- static STATUS ParseCertificatePolicy(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrDataBuffer *CertificatePolicy)
- {
- UINT8 *current_ptr = *ppCurrent;
- UINT32 length;
- UINT8* end_of_PolicyInformation = NULL;
- UINT32 temp;
- STATUS Status;
- UINT8 EncodingBytes;
- do{
- /* Certificate Policy is a SEQ of Policy Information */
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- end_of_PolicyInformation = current_ptr + length;
- while(current_ptr < end_of_PolicyInformation){
- /* Policy information is Seq of {Policy Identifier, Policy Qualifier [optional] */
- Status = ParseIdAndLength(¤t_ptr, end_of_PolicyInformation, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- // Policy Identifier is a Object ID
- Status = ParseOID(¤t_ptr, end_of_PolicyInformation, &temp, &CertificatePolicyOid[0][0],
- sizeof(CertificatePolicyOid)/sizeof(CertificatePolicyOid[0]),
- sizeof(CertificatePolicyOid[0]));
- if(Status != X509_STATUS_SUCCESS)
- break;
- if(temp >= Max_Certificatepolicy){
- /* this is a unsupported policy. Ignore */
- current_ptr+= length;
- continue;
- }
- /* We have a supported policy !!!! */
- // Next Field: PolicyQualifiers PolicyQualifiers is a SEQ of Policy Qualifier Info. However, we only support one Policy Qualifier Info
- Status = ParseIdAndLength(¤t_ptr, end_of_PolicyInformation, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- Status = ParseIdAndLength(¤t_ptr, end_of_PolicyInformation, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- Status = ParseOID(¤t_ptr, end_of_PolicyInformation, &temp, &CertificatePolicyQualifierIdOid[0][0],
- sizeof(CertificatePolicyQualifierIdOid)/sizeof(CertificatePolicyQualifierIdOid[0]),
- sizeof(CertificatePolicyQualifierIdOid[0]));
- if(Status != X509_STATUS_SUCCESS)
- break;
- if(temp >= Max_Certificatepolicy){
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- // we have a supported policy qualifier id. Qualifier can be a CHOICE{cPSuri, UserNotice}. Note : Parser only supports cPSuri
- Status = ParseIdAndLength(¤t_ptr, end_of_PolicyInformation, DER_ENCODING_IA5_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- CertificatePolicy->buffer = current_ptr;
- CertificatePolicy->length = length;
- current_ptr +=length;
- }
- }while(0);
- DBG_ASSERT(Status == X509_STATUS_SUCCESS);
- *ppCurrent = current_ptr;
- return Status;
- }
- #endif
- static STATUS ParseSubjectPublicKeyInfo(UINT8 **ppCurrent, UINT8 *pEnd, UINT8 **pworkbuffer, SessMgrCertificateFields* certificateFields)
- {
- UINT8 *current_ptr = *ppCurrent;
- UINT8 *workbuffer_ptr = *pworkbuffer;
- UINT32 length;
- SessMgrEllipticCurveParameter params = unknownParameter;
- STATUS Status;
- UINT8 EncodingBytes;
- SessMgrDataBuffer* Key;
- SessMgrPublicKeyAlgoType* KeyType;
- /* Subject public key consist of a Algo Identifier and a BIT String containing the actual key */
- Key = &certificateFields->subjectPublicKey;
- KeyType = &certificateFields->algorithmIdentifierForSubjectPublicKey;
- do{
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* We first get the algo identifier */
- Status = ParseAlgoIdentifier(¤t_ptr, pEnd, (UINT32*)KeyType, PublicKey_algo, ¶ms);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* Next is the Subject Public Key. It is a BIT string. */
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_BIT_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* current_ptr is over the number of padding bits for the BIT string . We expect this to always be zero since we are not dealing with bit level data */
- if(*current_ptr != 0x00){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- current_ptr++;
- certificateFields->EncodedSubjectPublicKey.buffer = current_ptr;
- certificateFields->EncodedSubjectPublicKey.length = length - 1;
- switch(*KeyType)
- {
- case X509_ecdsaPublicKey:
- // for ecdsa we know the length should be 66 bytes.
- if(length != 66){
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- Key->buffer = workbuffer_ptr;
- Key->length = sizeof(SessMgrEcdsaPublicKey);
- workbuffer_ptr += sizeof(SessMgrEcdsaPublicKey);
- Status = ParseEcdsaPublicKey(¤t_ptr, pEnd, (SessMgrEcdsaPublicKey * )(Key->buffer), (SessMgrEllipticCurveParameter)params);
- break;
- case X509_intel_sigma_epidGroupPublicKey_epid11:
- Key->buffer = workbuffer_ptr;
- Key->length = sizeof(SessMgrEpidGroupPublicKey);
- workbuffer_ptr += sizeof(SessMgrEpidGroupPublicKey);
- Status = ParseEpidPublicKey(¤t_ptr, pEnd, (SessMgrEpidGroupPublicKey * )(Key->buffer));
- #ifdef PRINT
- PrintEpidKey((void *)Key->buffer);
- #endif
- break;
- case X509_rsaPublicKey:
- Key->buffer = workbuffer_ptr;
- Key->length = sizeof(SessMgrRsaKey);
- workbuffer_ptr += sizeof(SessMgrRsaKey);
- Status = ParseRsaPublicKey(¤t_ptr, pEnd, (SessMgrRsaKey * )(Key->buffer));
- break;
- default:
- DBG_ASSERT(0);
- }
- }while(0);
- if(Status == X509_STATUS_SUCCESS){
- *pworkbuffer = workbuffer_ptr;
- *ppCurrent = current_ptr;
- }
- DBG_ASSERT(Status == X509_STATUS_SUCCESS);
- return Status;
- }
- static STATUS ParseRsaPublicKey(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrRsaKey * RsaKey)
- {
- UINT8 *current_ptr = *ppCurrent;
- UINT32 length;
- STATUS Status;
- UINT8 EncodingBytes;
- /* The data portion of the BIT string contains a sequence of Seq { n , e} where n and e are integers */
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- Status = ParseInteger(¤t_ptr, pEnd, &RsaKey->n, FALSE, FALSE, NULL);
- if(Status != X509_STATUS_SUCCESS)
- return X509_STATUS_ENCODING_ERROR;
- Status = ParseInteger(¤t_ptr, pEnd, &RsaKey->e, FALSE, FALSE, NULL);
- if(Status != X509_STATUS_SUCCESS)
- return X509_STATUS_ENCODING_ERROR;
- *ppCurrent = current_ptr;
- return X509_STATUS_SUCCESS;
- }
- static STATUS ParseEpidPublicKey(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrEpidGroupPublicKey * EpidKey)
- {
- UINT8 *current_ptr = *ppCurrent;
- UINT32 length;
- SessMgrDataBuffer DataBuf;
- STATUS Status;
- UINT8 EncodingBytes;
- do{
- /* We are expecting a sequence of {groupId [Integer], h1 [ECPoint], h2 [ECPoint], w [G2ECPoint] */
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* Parse Integer */
- Status = ParseInteger(¤t_ptr, pEnd, &DataBuf, FALSE, FALSE, NULL);
- if(Status != X509_STATUS_SUCCESS)
- break;
- Status = swapendian_memcpy((UINT8 *)&EpidKey->groupId, sizeof(UINT32), DataBuf.buffer, DataBuf.length);
- if(Status != X509_STATUS_SUCCESS)
- break;
- // Next Field : h1 [octet string] This is a ECPoint which is a octet string
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_OCTET_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* Make sure it has the first bype as 0x04 indicating key is uncompressed */
- if(*current_ptr != 0x04){
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- current_ptr++;
- EpidKey->h1x = current_ptr;
- EpidKey->h1y = current_ptr + 32;
- current_ptr += 64;
- // Next Field : h2 [octet string] This is a ECPoint which is a octet string
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_OCTET_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* Make sure it has the first bype as 0x04 indicating key is uncompressed */
- if(*current_ptr != 0x04){
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- current_ptr++;
- EpidKey->h2x = current_ptr;
- EpidKey->h2y = current_ptr + 32;
- current_ptr += 64;
- // Next Field : w [octet string] This is a ECPoint which is a octet string
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_OCTET_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* Make sure it has the first bype as 0x04 indicating key is uncompressed */
- if(*current_ptr != 0x04){
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- current_ptr++;
- EpidKey->wx0 = current_ptr;
- EpidKey->wx1 = current_ptr + 32;
- EpidKey->wx2 = current_ptr + 64;
- EpidKey->wy0 = current_ptr + 96;
- EpidKey->wy1 = current_ptr + 128;
- EpidKey->wy2 = current_ptr + 160;
- current_ptr += 192;
- }while(0);
- *ppCurrent = current_ptr;
- return Status;
- }
- static STATUS ParseEcdsaPublicKey(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrEcdsaPublicKey * EcDsaKey, SessMgrEllipticCurveParameter params)
- {
- UINT8 *current_ptr = *ppCurrent;
- STATUS Status = X509_STATUS_SUCCESS;
- #ifdef X509_FOR_PSE_PR
- UNUSED(pEnd);
- #endif
- do{
- /* Ecdsa Public Key is a Octet string. The SubjectPublicKey in the X509 definitiion is a bit string.
- We use the following logic to convert the Octet String as a bit string as per the Verifier Cert Spec defined by Xiaoyu. */
- /* First octet of bit string is 0x04 indicating key is uncompressed.
- Note: The Key is in OCTET String form and we convert it to BIT STRING. Format : 0x04 | 64-bytes of keys */
- if(*current_ptr != 0x04){
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- current_ptr++;
- EcDsaKey->px = current_ptr;
- EcDsaKey->py = current_ptr + ECDSA_KEY_ELEMENT_SIZE;
- current_ptr += ECDSA_KEY_SIZE;
- EcDsaKey->eccParameter = params;
- }while(0);
- DBG_ASSERT(Status == X509_STATUS_SUCCESS);
- *ppCurrent = current_ptr;
- return Status;
- }
- /* We will never send an OID to the caller. All the OID are matched to a corresponding enumerated type and sent to the caller. */
- static STATUS ParseOID(UINT8 **ppCurrent, UINT8 *pEnd, UINT32 *EnumVal, const UINT8 *OidList, UINT32 Max_Entries, UINT32 EntrySize )
- {
- UINT8 *current_ptr = *ppCurrent;
- UINT32 length;
- UINT32 i;
- STATUS Status;
- UINT8 EncodingBytes;
- do{
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_OBJECT_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* We have a encoded list of hard coded OIDs that we support in an array. Just compare the OID with that array. */
- for(i = 0;i< Max_Entries; i++)
- {
- //
- // current_ptr could be out of bounds (speculatively)
- // and looping one too many times (also speculatively)
- // would be bad
- //
- sgx_lfence();
- if(memcmp(current_ptr, OidList, length) == 0){
- /* We found a match. i is the algorithm number that the caller is looking for */
- *EnumVal= i;
- Status = X509_STATUS_SUCCESS;
- break;
- }
- OidList+=EntrySize;
- }
- if(i >= Max_Entries) {
- /* Never found a match */
- *EnumVal= i;
- Status = X509_STATUS_UNKNOWN_OID;
- }
- current_ptr += length;
- }while(0);
- DBG_ASSERT(Status == X509_STATUS_SUCCESS || Status == X509_STATUS_UNKNOWN_OID);
- *ppCurrent = current_ptr;
- return Status;
- }
- static STATUS ParseSignatureValue(UINT8 **ppCurrent, UINT8 *pEnd, UINT8 **pworkbuffer, UINT32 WorkBufferSize, SessMgrDataBuffer *SignatureValueBuf, UINT8 SignatureAlgoId)
- {
- UINT8 *current_ptr = *ppCurrent;
- UINT32 length;
- UINT8 *workbuffer_ptr;
- STATUS Status;
- SessMgrDataBuffer DataBuf;
- UINT8 EncodingBytes;
- #ifdef X509_FOR_PSE_PR
- UNUSED(WorkBufferSize);
- #endif
- workbuffer_ptr = *pworkbuffer;
- do{
- /* SignatureValue is a BIT string. The content within the BIT string is based on the signature algorithm */
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_BIT_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS )
- break;
- /* Next Byte is the number of padded. Because this is a signature, we expect the resulting value to be a multiple of 8 bits meaning no padding will be necessery */
- //
- // current_ptr could be out of bounds (speculatively)
- //
- sgx_lfence();
- if(*current_ptr != 0){
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- //
- // the inc below requires this (i'm choosing to care about **read** buffer overflows)
- //
- if ((current_ptr + 1) >= pEnd) {
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- /* increment current pointer. decrement length to reflect size of actual bit string excluding the padding data*/
- current_ptr++;
- length--;
- /* Rest of the buffer is parsed based on the algo */
- switch(SignatureAlgoId)
- {
- /* ECDSA based sign algorithm */
- case X509_ecdsa_with_SHA1:
- case X509_ecdsa_with_SHA256:
- /* For ECDSA, Signature value is represented as a SEQ {r, s} where r and s are integers. We use the workbuffer to store this */
- /* First memset the buffers where keys will be copied to */
- memset(workbuffer_ptr, 0, ECDSA_SIGNATURE_SIZE);
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* Parse R and S */
- Status = ParseInteger(¤t_ptr, pEnd, &DataBuf, FALSE, FALSE, NULL);
- if(Status != X509_STATUS_SUCCESS || DataBuf.length > ECDSA_SIGNATURE_MAX_SIZE_R ){
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- SESSMGR_MEMCPY_S(workbuffer_ptr + (ECDSA_SIGNATURE_MAX_SIZE_R - DataBuf.length), WorkBufferSize - (workbuffer_ptr - *pworkbuffer), DataBuf.buffer, DataBuf.length);
- workbuffer_ptr += ECDSA_SIGNATURE_MAX_SIZE_R;
- Status = ParseInteger(¤t_ptr, pEnd, &DataBuf, FALSE, FALSE, NULL);
- if(Status != X509_STATUS_SUCCESS || DataBuf.length > ECDSA_SIGNATURE_MAX_SIZE_S){
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- SESSMGR_MEMCPY_S(workbuffer_ptr + (ECDSA_SIGNATURE_MAX_SIZE_S - DataBuf.length), WorkBufferSize - (workbuffer_ptr - *pworkbuffer), DataBuf.buffer, DataBuf.length);
- workbuffer_ptr += ECDSA_SIGNATURE_MAX_SIZE_S;
- break;
- /* All the RSA algorithms */
- case X509_sha1withRSAEncryption:
- case X509_sha256WithRSAEncryption:
- /* Assuming here that all RSA algorithms just have a bit string signaure */
- if(length > RSA_SIGNATURE_SIZE){
- Status = X509_STATUS_ENCODING_ERROR;
- break;
- }
- memset(workbuffer_ptr, 0 , length);
- SESSMGR_MEMCPY_S(workbuffer_ptr, WorkBufferSize - (workbuffer_ptr - *pworkbuffer), current_ptr, length);
- workbuffer_ptr += length;
- current_ptr +=length;
- break;
- default:
- DBG_ASSERT(0);
- Status = X509_STATUS_INVALID_ARGS;
- }
- }while(0);
- if(Status == X509_STATUS_SUCCESS){
- // Signature value has been parsed successfully. Store the offset in the workbuffer in the DataBuffer that will be passed back to the caller
- SignatureValueBuf->buffer = *pworkbuffer;
- // length is the amount of work buffer we have used up
- SignatureValueBuf->length = static_cast<Uint32>(workbuffer_ptr - *pworkbuffer);
- }else{
- DBG_ASSERT(0);
- }
- *pworkbuffer = workbuffer_ptr;
- *ppCurrent = current_ptr;
- return Status;
- }
- static STATUS ParseAlgoIdentifier(UINT8 **ppCurrent, UINT8 *pEnd, UINT32* algoId, AlgorithmTypes Type, SessMgrEllipticCurveParameter *params)
- {
- /*****
- Format : Sequence Id + length + Object Id + length + OID value + parameters (optional)
- *****/
- UINT8 *current_ptr = *ppCurrent;
- UINT32 length;
- UINT8 *end_of_sequence;
- STATUS Status;
- UINT8 EncodingBytes;
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- end_of_sequence = current_ptr + length;
- switch(Type){
- case signature_algo:
- Status = ParseOID(¤t_ptr, pEnd, algoId, &HardCodedSignatureAlgorithmOid[0][0],
- static_cast<uint32_t>(sizeof(HardCodedSignatureAlgorithmOid)/sizeof(HardCodedSignatureAlgorithmOid[0])),
- sizeof(HardCodedSignatureAlgorithmOid[0]));
- break;
- case PublicKey_algo:
- Status = ParseOID(¤t_ptr, pEnd, algoId, &HardCodedPublicKeyAlgorithmOid[0][0],
- static_cast<uint32_t>(sizeof(HardCodedPublicKeyAlgorithmOid)/sizeof(HardCodedPublicKeyAlgorithmOid[0])),
- sizeof(HardCodedPublicKeyAlgorithmOid[0]));
- break;
- case Hash_algo:
- Status = ParseOID(¤t_ptr, pEnd, algoId, &HashAlgorithmOid[0][0],
- static_cast<uint32_t>(sizeof(HashAlgorithmOid)/sizeof(HashAlgorithmOid[0])),
- sizeof(HashAlgorithmOid[0]));
- break;
- default:
- DBG_ASSERT(0);
- }
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- if(current_ptr < end_of_sequence){
- /* We have some parameters */
- Status = ParseAlgoParameters(¤t_ptr, end_of_sequence, (UINT32 *)params);
- if(Status == X509_STATUS_UNSUPPORTED_PARAMETER){
- // As per spec, we just move on.
- current_ptr = end_of_sequence;
- *params = unknownParameter;
- Status = X509_STATUS_SUCCESS;
- }
- if(Status != X509_STATUS_SUCCESS)
- Status = X509_STATUS_ENCODING_ERROR;
- }else{
- *params=unknownParameter;
- }
- *ppCurrent = current_ptr;
- return Status;
- }
- static STATUS ParseAlgoParameters(UINT8 **ppCurrent, UINT8 *pEnd, UINT32* param)
- {
- UINT8 *current_ptr = *ppCurrent;
- UINT32 length;
- UINT32 i;
- STATUS Status = X509_STATUS_SUCCESS;
- UINT8 EncodingBytes;
- if ((!param) || ((current_ptr + 1) >= pEnd))
- {
- DBG_ASSERT(0);
- return X509_STATUS_INVALID_ARGS;
- }
- /* current_ptr is over the parameters. We currently support a NULL parameter or an object ID specifiying some algo specific data */
- switch(*current_ptr)
- {
- case DER_ENCODING_NULL_ID:
- current_ptr++;
- /* NULL id is always followed by length 0x00 */
- if(*current_ptr != 0)
- {
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- current_ptr++;
- *param = unknownParameter;
- break;
- case DER_ENCODING_OBJECT_ID:
- current_ptr++;
- /* Get Length of object identifier */
- Status = DecodeLength(current_ptr, pEnd, &length, &EncodingBytes);
- if(Status != X509_STATUS_SUCCESS)
- break;
- current_ptr += EncodingBytes;
- /* This can describe the curve */
- for(i = 0;i< MaxElipticCurveOidSupported; i++)
- {
- if(memcmp(current_ptr, EllipticCurveOid[i], length) == 0){
- /* We found a match. "i+1" is the algorithm number that the caller is looking for */
- *param = i;
- break;
- }
- }
- if(i >= MaxElipticCurveOidSupported) {
- /* Never found a match */
- DBG_ASSERT(0);
- *param = unknownParameter;
- Status = X509_STATUS_ENCODING_ERROR;
- }
- current_ptr+=length;
- break;
- default:
- Status = X509_STATUS_UNSUPPORTED_PARAMETER;
- break;
- // unknown parameter. We ignore this.
- }
- *ppCurrent = current_ptr;
- return Status;
- }
- static STATUS ParseName(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrX509Name* Name)
- {
- UINT8* end_of_sequence = NULL;
- UINT8 *current_ptr = *ppCurrent;
- UINT32 length;
- STATUS Status;
- UINT8 EncodingBytes;
- UINT32 NameType;
- memset(Name, 0, sizeof(SessMgrX509Name));
- do{
- Name->DistinguishedName = (char *)current_ptr;
- /* Format : Sequence [ Set [ Sequence [ OID Value] ] ] */
- Status = ParseIdAndLength(¤t_ptr, pEnd, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- Name->DistinguishedNameSize = length + EncodingBytes + 1;
- end_of_sequence = current_ptr + length;
- /* Because Set can have variable number of data underneath it, we need to cap it using the length of the sequence
- We will use variable End_of_set and loop through until end is reached. */
- while(current_ptr < end_of_sequence){
- Status = ParseIdAndLength(¤t_ptr, end_of_sequence, DER_ENCODING_SET_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- Status = ParseIdAndLength(¤t_ptr, end_of_sequence, DER_ENCODING_SEQUENCE_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS)
- break;
- /* Expected value : Attribute type (OID) and value (Can be anything) */
- Status = ParseOID(¤t_ptr, end_of_sequence, &NameType, &HardCodedNameOid[0][0],
- static_cast<uint32_t>(sizeof(HardCodedNameOid)/sizeof(HardCodedNameOid[0])),
- sizeof(HardCodedNameOid[0]));
- // We might have some cases where we are getting an Unknown OID which we just ignore.
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_UNKNOWN_OID){
- DBG_ASSERT(0);
- break;
- }
- /* Value can be any type. Mostly some form of ascii string */
- Status = ParseIdAndLength(¤t_ptr, end_of_sequence, DER_ENCODING_UTF8_ID, &length, &EncodingBytes, TRUE);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status == X509_STATUS_NOT_FOUND){
- // Has to be one of UTF8 or PRINTABLE_STRING or IA5
- Status = ParseIdAndLength(¤t_ptr, end_of_sequence, DER_ENCODING_PRINTABLE_STRING_ID, &length, &EncodingBytes, TRUE);
- if(Status != X509_STATUS_SUCCESS && Status != X509_STATUS_NOT_FOUND)
- break;
- if(Status == X509_STATUS_NOT_FOUND){
- Status = ParseIdAndLength(¤t_ptr, end_of_sequence, DER_ENCODING_IA5_STRING_ID, &length, &EncodingBytes, FALSE);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- break;
- }
- }
- }
- switch(NameType)
- {
- case commonName:
- Name->commonName = (char *)current_ptr;
- Name->commonNameSize = length;
- break;
- case organization:
- Name->organization = (char *)current_ptr;
- Name->organizationSize = length;
- break;
- case country:
- Name->country = (char *)current_ptr;
- Name->countrySize = length;
- break;
- case locality:
- Name->locality = (char *)current_ptr;
- Name->localitySize = length;
- break;
- case state:
- Name->state = (char *)current_ptr;
- Name->stateSize = length;
- break;
- case organizationUnit:
- Name->organizationUnit = (char *)current_ptr;
- Name->organizationUnitSize = length;
- break;
- case UserId:
- Name->UserId = (char *)current_ptr;
- Name->UserIdSize = length;
- break;
- default:
- // Dont support this NameType. Just continue.
- break;
- }
- current_ptr += length;
- }
- }while(0);
- *ppCurrent = current_ptr;
- return Status;
- }
- #define DecodeTime_FourBytes(current_ptr) ((1000*( (*current_ptr) - 0x30)) + \
- (100*( *(current_ptr+1) - 0x30)) + \
- (10*( *(current_ptr+2) - 0x30)) + \
- (*(current_ptr + 3) - 0x30)) \
- #define DecodeTime_TwoBytes(current_ptr) ((10*( (*current_ptr) - 0x30)) + \
- (*(current_ptr + 1) - 0x30)) \
- #if 0
- UINT32 DecodeTime(UINT8 *current_ptr, UINT8 length)
- {
- UINT32 value = 0;
- UINT32 digit;
- int i;
- for(i=0; i<length - 1;i++)
- {
- digit = *current_ptr - 0x30;
- digit = digit * Pow(10, length - i - 1);
- value += digit;
- current_ptr++;
- }
- return value;
- }
- #endif
- static STATUS ParseTime(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrDateTime* DateTime)
- {
- /* Id : Either UTC Time or Generalized Time */
- /*****
- Supported UTC formats : YYMMDDhhmmZ
- YYMMDDhhmm+hhmm
- YYMMDDhhmm-hhmm
- YYMMDDhhmmssZ
- YYMMDDhhmmss+hhmm
- YYMMDDhhmmss-hhmm
- *****/
- UINT8 *current_ptr = *ppCurrent;
- UINT32 length;
- BOOL isUTC;
- STATUS Status;
- UINT8 EncodingBytes;
- UINT8 *date_start_ptr;
- DateTime->date.data = 0;
- DateTime->time.data = 0;
- /* Check whether current_ptr is pointing to UTC time or Generalized time*/
- if(*current_ptr == DER_ENCODING_UTC_TIME_ID){
- /* Year format is YY */
- isUTC = TRUE;
- }
- else if(*current_ptr == DER_ENCODING_GENERALIZED_TIME_ID){
- /* Year format is YYYY */
- isUTC = FALSE;
- }else{
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- current_ptr++;
- /* get Length of the time */
- Status = DecodeLength(current_ptr, pEnd, &length, &EncodingBytes);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- current_ptr += EncodingBytes;
- date_start_ptr = current_ptr;
- /* Only difference between generalized and UTC is number of digits for the years.
- UTC has 2 digits and Generalized has 4 digits */
- if(!isUTC){
- DateTime->date.yearMonthDay.year = static_cast<short unsigned int>(DecodeTime_FourBytes(current_ptr));
- current_ptr += 4;
- }else{
- // per rfc3280, if XX >= 50 then 19XX, otherwise 20XX. However, here we always use 20XX.
- DateTime->date.yearMonthDay.year = static_cast<short unsigned int>(DecodeTime_TwoBytes(current_ptr));
- current_ptr += 2;
- DateTime->date.yearMonthDay.year = static_cast<short unsigned int>(DateTime->date.yearMonthDay.year + 2000);
- }
- /* The next 8 bytes are common for both UTC and Generalized time */
- DateTime->date.yearMonthDay.month = DecodeTime_TwoBytes(current_ptr) & 0xF;
- current_ptr += 2;
- DateTime->date.yearMonthDay.day = DecodeTime_TwoBytes(current_ptr) & 0x3F;
- current_ptr += 2;
- DateTime->time.hourMinuteSecond.hour = DecodeTime_TwoBytes(current_ptr) & 0x3F;
- current_ptr += 2;
- DateTime->time.hourMinuteSecond.minute = DecodeTime_TwoBytes(current_ptr) & 0x3F;
- current_ptr += 2;
- /* Next character can be a numeral(incase we have seconds), +, - or Z */
- if(isdigit(*current_ptr)){
- /* we have second. Get the next two bytes as seconds. */
- DateTime->time.hourMinuteSecond.second = DecodeTime_TwoBytes(current_ptr) & 0x3F;
- current_ptr += 2;
- }
- /* Next character has to be +, - or Z */
- switch(*current_ptr)
- {
- case '-':
- DateTime->time.hourMinuteSecond.timezone_is_neg = true;
- /* fallthrough */
- case '+':
- current_ptr++;
- DateTime->time.hourMinuteSecond.timezone_hour = DecodeTime_TwoBytes(current_ptr) & 0x3F;
- current_ptr += 2;
- DateTime->time.hourMinuteSecond.timezone_minute = DecodeTime_TwoBytes(current_ptr) & 0x3F;
- current_ptr += 2;
- break;
- case 'Z':
- /* End of time */
- current_ptr++;
- break;
- default:
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- // ensure the length parsed is equal to the specified length
- if ((current_ptr - date_start_ptr) != length)
- {
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- // date sanity check
- if (DateTime->date.yearMonthDay.year < 2000 || DateTime->date.yearMonthDay.year >= 2137 ||
- DateTime->date.yearMonthDay.month < 1 || DateTime->date.yearMonthDay.month > 12 ||
- DateTime->date.yearMonthDay.day < 1 || DateTime->date.yearMonthDay.day > 31 ||
- DateTime->time.hourMinuteSecond.hour > 24 ||
- DateTime->time.hourMinuteSecond.minute > 60 ||
- DateTime->time.hourMinuteSecond.second > 60 ||
- DateTime->time.hourMinuteSecond.timezone_hour > 24 ||
- DateTime->time.hourMinuteSecond.timezone_minute > 60)
- {
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- *ppCurrent = current_ptr;
- return X509_STATUS_SUCCESS;
- }
- /**
- \param[in] Buffer Buffer which is pointing to a length field in Asn DER encoded form
- \param[out] Length Length of the Asn DER encoded type in bytes
- \param[out] EncodingBytes Number of bytes used for the encoding of the length
- \retval X509_STATUS_SUCCESS
- \retval STATUS_INVALID_PARAMS THere was some error in parsing the ASN Der encoded buffer.
- @brief Return length of the ASN DER encoded type
- */
- static STATUS DecodeLength(UINT8* Buffer, UINT8* BufferEnd, UINT32* Length, UINT8* EncodingBytes)
- {
- //
- // some spectre vulnerabilities in here
- //
- // stop speculation here to make sure Buffer[0] is in bounds
- // before reading
- //
- sgx_lfence();
- if(Buffer[0] < 0x81){
- /* length is only one byte */
- *Length = Buffer[0];
- *EncodingBytes = 1;
- } else if ((Buffer[0] == 0x81) && (&Buffer[1] < BufferEnd)) {
- //
- // lfence for Buffer[1]
- //
- sgx_lfence();
- /* length is two bytes */
- *Length = Buffer[1];
- *EncodingBytes = 2;
- } else if ((Buffer[0] == 0x82) && (&Buffer[2] < BufferEnd)) {
- //
- // lfence for Buffer[2]
- //
- sgx_lfence();
- /* length is 3 bytes */
- *Length = (Buffer[1] << 8) + Buffer[2];
- *EncodingBytes = 3;
- }else{
- return X509_STATUS_ENCODING_ERROR;
- }
- //
- // check for unsigned integer overflow
- //
- UINT32 tempLength = *EncodingBytes + *Length;
- if (((size_t) Buffer + tempLength) >= tempLength) {
- if ((Buffer + tempLength) > BufferEnd) {
- return X509_STATUS_ENCODING_ERROR;
- }
- //
- // X.509 cert includes length fields that
- // an attacker can control
- //
- sgx_lfence();
- }
- else {
- return X509_STATUS_ENCODING_ERROR;
- }
- return X509_STATUS_SUCCESS;
- }
- static void SwapEndian(UINT8* ptr, int length)
- {
- UINT8 temp;
- int i;
- for(i=0;i<length/2;i++)
- {
- temp = *(ptr + i);
- *(ptr + i) = *(ptr + length - i - 1);
- *(ptr + length - i - 1) = temp;
- }
- }
- #ifndef X509_FOR_PSE_PR
- static int Pow(int num, int exp)
- {
- int i;
- for(i=0;i<(exp -1);i++)
- num *=num;
- return num;
- }
- #endif
- /*
- This function is used to copy a variable length Big-Endian buffer to a little-endian static length buffer. the buffer is copied over and endianness changed.
- Does not affect Source Buffer. Copies dest buffer uses some ptr arithmatic and converts endianness.
- */
- static STATUS swapendian_memcpy(UINT8 *DestPtr, UINT32 DestLen, UINT8 *SrcPtr, UINT32 SrcLen)
- {
- if( (!DestPtr) || (!SrcPtr) || (DestLen < SrcLen))
- return STATUS_INVALID_PARAMS;
- memset(DestPtr, 0, DestLen);
- SESSMGR_MEMCPY_S(DestPtr + DestLen - SrcLen, DestLen, SrcPtr, SrcLen);
- SwapEndian(DestPtr, DestLen);
- return STATUS_SUCCESS;
- }
- /**
- @brief ASN DER encoding follows the TLV format : Type Identifier || Length || Value
- 1. This function will parse the Type ID and Length, validate it with Expected Id and some encoding rules.
- 2. If no errors, function will move the current ptr to the value.
- \param[in] pCurrentPtr This is a pointer to the current pointer. The function will move the current pointer after parsing the ID and length
- \param[in] ExpectedId Expected Type identifier
- \param[out] Length Length in Bytes of the "Value"
- \param[out] EncodingBytes Number of Bytes used to encode the length field.
- \param[in] Optional Is the ExpectedIdOptional
- @retval X509_STATUS_SUCCESS ID and length were parsed and verified successfully.
- @retval X509_STATUS_NOT_FOUND This value is only returned
- @retval STATUS_ENCODING_ERROR Some error in the encoding of the certificate.
- */
- static STATUS ParseIdAndLength(UINT8 **ppCurrent, UINT8 *pEnd, UINT8 ExpectedId, UINT32* Length, UINT8* EncodingBytes, BOOL Optional)
- {
- UINT8* current_ptr = *ppCurrent;
- STATUS Status;
- //
- // could be here speculatively and
- // current_ptr be out of bounds
- //
- sgx_lfence();
- if(*current_ptr != ExpectedId){
- if(Optional)
- return X509_STATUS_NOT_FOUND;
- else{
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- }
- current_ptr++;
- if (current_ptr != pEnd) {
- Status = DecodeLength(current_ptr, pEnd, Length, EncodingBytes);
- if(Status != X509_STATUS_SUCCESS){
- DBG_ASSERT(0);
- return X509_STATUS_ENCODING_ERROR;
- }
- current_ptr += *EncodingBytes;
- *ppCurrent = current_ptr;
- return X509_STATUS_SUCCESS;
- }
- else {
- return X509_STATUS_ENCODING_ERROR;
- }
- }
- #ifndef X509_FOR_PSE_PR
- /*
- * This function expects the trusted time to be available from the OCSP parsing and stored in the SessMgrCtx.
- * This call is protected by the Mutex we acquire when we get the ProcessS2GetS3 call.
- */
- STATUS StoreTrustedTime(SessMgrDateTime TrustedTime)
- {
- STATUS Status;
- STORAGE_FILE_ATTRIB Blob;
- STORAGE_OPERATION_FLAGS StorageFlags = {0};
- NTP_TIMESTAMP NtpTime = {0,0};
- Status = ConvertTimeToNtp(TrustedTime, &NtpTime );
- if(Status != STATUS_SUCCESS){
- DBG_ASSERT(0);
- return Status;
- }
- // We have the time in NTP. Call PrtcSetTime. This will give us an offset which we can use to find out current time.
- Status = PrtcSetTime(&NtpTime, &gSessmgrCtx.TrustedTime.RtcOffset);
- if(Status != STATUS_SUCCESS){
- DBG_ASSERT(0);
- return Status;
- }
- gSessmgrCtx.TrustedTime.Seconds = NtpTime.Seconds;
- // Store RTC offset in the Blob
- SESSMGR_INIT_BLOB_ATTRIB(Blob);
- Blob.Attributes.BlobType = AR_BLOB;
- StorageFlags.Data = 0;
- Status = gSessmgrCtx.StorageProtocol->Write(gSessmgrCtx.StorageProtocol,
- SESS_MGR_TRUSTED_TIME_NVAR_NAME,
- &Blob, &StorageFlags,
- sizeof(gSessmgrCtx.TrustedTime),
- &gSessmgrCtx.TrustedTime, 0);
- if(Status != STATUS_SUCCESS){
- DBG_ASSERT(0);
- return Status;
- }
- return STATUS_SUCCESS;
- }
- STATUS ConvertTimeToNtp(SessMgrDateTime Time, NTP_TIMESTAMP *NtpTime)
- {
- STATUS Status;
- RTC_TIME RtcTime;
- TZ_DST TimeZoneAndDST;
- memset(&RtcTime, 0, sizeof(RTC_TIME));
- memset(NtpTime, 0, sizeof(NTP_TIMESTAMP));
- if (Time.date.yearMonthDay.year < 2000 || Time.date.yearMonthDay.year >= 2137)
- return STATUS_FAILURE;
- RtcTime.Year = (UINT8)(Time.date.yearMonthDay.year - 2000);
- RtcTime.Month = (UINT8)Time.date.yearMonthDay.month;
- RtcTime.Day = (UINT8)Time.date.yearMonthDay.day;
- RtcTime.Hour = (UINT8)Time.time.hourMinuteSecond.hour;
- RtcTime.Min = (UINT8)Time.time.hourMinuteSecond.minute;
- RtcTime.Sec = (UINT8)Time.time.hourMinuteSecond.second;
- RtcTime.Status.DM = 1; // DM = 1 => Binary data representation.
- RtcTime.Status.HOURFORM = 1; // HOURFORM = 1 => 24 hour
- TimeZoneAndDST.DST = 0;
- TimeZoneAndDST.HalfHourAdjust = Time.time.hourMinuteSecond.timezone_minute ? 1 : 0;
- TimeZoneAndDST.RSVD = 0;
- TimeZoneAndDST.TimeZone = (Time.time.hourMinuteSecond.timezone_is_neg ? TIME_ZONE_OFFSET_SIGN_MASK : 0) |
- Time.time.hourMinuteSecond.timezone_hour;
- Status = PrtcLocalToNtp(&RtcTime, TimeZoneAndDST, NtpTime);
- if(Status != STATUS_SUCCESS){
- DBG_ASSERT(0);
- return Status;
- }
- // PrtcLocalToNtp has a starting offset of year 1900 and will overflow in year 2037
- // Shift the offset to start at year 2000, so that we can operate in years 2000-2137
- NtpTime->Seconds -= SECONDS_FROM_1900_TO_2000;
- return STATUS_SUCCESS;
- }
- #endif // #ifndef X509_FOR_PSE_PR
|