//+-------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996 - 1999 // // File: crypt.cpp // // Contents: Cert Server wrapper routines // // History: 17-Oct-96 vich created // //--------------------------------------------------------------------------- #include #pragma hdrstop #include #define CRYPT32_SP3_ONLY #ifdef CRYPT32_SP3_ONLY #ifdef __cplusplus extern "C" { #endif #include "keygen.h" #ifdef __cplusplus } #endif #include "crypttls.h" #include "ossconv.h" #include "ossutil.h" // All the *pInfo extra stuff needs to be aligned #define INFO_LEN_ALIGN(Len) (((Len) + 7) & ~7) HCRYPTOSSGLOBAL hOssGlobal; //+------------------------------------------------------------------------- // Function: GetPog // // Synopsis: Initialize thread local storage for the asn libs // // Returns: pointer to an initialized OssGlobal data structure //-------------------------------------------------------------------------- __inline OssGlobal * GetPog(VOID) { return(I_CryptGetOssGlobal(hOssGlobal)); } HRESULT HError(VOID) { HRESULT hr; hr = GetLastError(); if (hr <= 0xffff) { hr = HRESULT_FROM_WIN32(hr); } if (!FAILED(hr)) { // somebody failed a call without properly setting an error condition hr = E_UNEXPECTED; } return(hr); } VOID OssX509GetIA5ConvertedToUnicode( IN IA5STRING *pOss, IN DWORD dwFlags, OPTIONAL OUT LPWSTR *ppwsz, IN OUT BYTE **ppbExtra, IN OUT LONG *plRemainExtra) { OssUtilGetIA5StringConvertedToUnicode( pOss->length, pOss->value, dwFlags, ppwsz, ppbExtra, plRemainExtra); } VOID OssX509GetObjectId( IN ObjectID *pOss, IN DWORD dwFlags, OPTIONAL OUT CHAR **pInfo, IN OUT BYTE **ppbExtra, IN OUT LONG *plRemainExtra) { DWORD cb; DWORD cbExtra; char ach[MAX_PATH]; LONG lRemainExtra; cb = sizeof(ach); if (!OssConvFromObjectIdentifier(pOss->count, pOss->value, ach, &cb)) { goto error; } CSASSERT(strlen(ach) + 1 == cb); cbExtra = INFO_LEN_ALIGN(cb); lRemainExtra = *plRemainExtra; lRemainExtra -= cbExtra; if (0 <= lRemainExtra) { *pInfo = (char *) *ppbExtra; CopyMemory(*pInfo, ach, cb); *ppbExtra += cbExtra; } *plRemainExtra = lRemainExtra; error: ; } __inline VOID OssX509GetAlgorithmParameters( IN OpenType *pOss, IN DWORD dwFlags, OPTIONAL OUT CRYPT_OBJID_BLOB *pInfo, IN OUT BYTE **ppbExtra, IN OUT LONG *plRemainExtra) { OssUtilGetOctetString( pOss->length, (BYTE *) pOss->encoded, dwFlags, pInfo, ppbExtra, plRemainExtra); } VOID OssX509GetAlgorithm( IN AlgorithmIdentifier *pOss, IN DWORD dwFlags, OPTIONAL OUT CRYPT_ALGORITHM_IDENTIFIER *pInfo, IN OUT BYTE **ppbExtra, IN OUT LONG *plRemainExtra) { if (0 <= *plRemainExtra) { ZeroMemory((VOID *) pInfo, sizeof(*pInfo)); } OssX509GetObjectId( &pOss->algorithm, dwFlags, &pInfo->pszObjId, ppbExtra, plRemainExtra); if (pOss->bit_mask & parameters_present) { OssX509GetAlgorithmParameters( &pOss->parameters, dwFlags, &pInfo->Parameters, ppbExtra, plRemainExtra); } } __inline VOID OssX509GetPublicKeyBlob( IN BITSTRING const *pOss, IN DWORD dwFlags, OPTIONAL OUT CRYPT_BIT_BLOB *pInfo, IN OUT BYTE **ppbExtra, IN OUT LONG *plRemainExtra) { OssUtilGetBitString( pOss->length, pOss->value, dwFlags, pInfo, ppbExtra, plRemainExtra); } VOID OssX509GetPublicKeyInfo( IN SubjectPublicKeyInfo *pOss, IN DWORD dwFlags, OPTIONAL OUT CERT_PUBLIC_KEY_INFO *pInfo, IN OUT BYTE **ppbExtra, IN OUT LONG *plRemainExtra) { OssX509GetAlgorithm( &pOss->algorithm, dwFlags, &pInfo->Algorithm, ppbExtra, plRemainExtra); OssX509GetPublicKeyBlob( &pOss->subjectPublicKey, dwFlags, &pInfo->PublicKey, ppbExtra, plRemainExtra); } //+------------------------------------------------------------------------- // Decode into an allocated, OSS formatted info structure // // Called by the OssX509*Decode() functions. //-------------------------------------------------------------------------- __inline BOOL OssInfoDecodeAndAlloc( IN int pdunum, IN const BYTE *pbEncoded, IN DWORD cbEncoded, OUT VOID **ppOssInfo) { return(OssUtilDecodeAndAllocInfo( GetPog(), pdunum, pbEncoded, cbEncoded, ppOssInfo)); } //+------------------------------------------------------------------------- // Free an allocated, OSS formatted info structure // // Called by the OssX509*Decode() functions. //-------------------------------------------------------------------------- VOID OssInfoFree( IN int pdunum, IN VOID *pOssInfo) { if (NULL != pOssInfo) { DWORD dwErr = GetLastError(); // TlsGetValue globbers LastError OssUtilFreeInfo(GetPog(), pdunum, pOssInfo); SetLastError(dwErr); } } //+------------------------------------------------------------------------- // KeyGen Info Decode (OSS X509) //-------------------------------------------------------------------------- BOOL DecodeKeyGen( IN BYTE const *pbEncoded, IN DWORD cbEncoded, IN DWORD dwFlags, OUT VOID *pInfo, IN OUT DWORD *pcbInfo) { BOOL fResult = FALSE; HRESULT hr; SignedPublicKeyAndChallenge *pOssInfo = NULL; CERT_KEYGEN_REQUEST_INFO *pcgi; BYTE *pbExtra; LONG lRemainExtra; LONG lAlignExtra; if (pInfo == NULL) { *pcbInfo = 0; } if (0 == hOssGlobal) { hOssGlobal = I_CryptInstallOssGlobal(keygen, 0, NULL); if (0 == hOssGlobal) { goto error; } } if (!OssInfoDecodeAndAlloc( SignedPublicKeyAndChallenge_PDU, pbEncoded, cbEncoded, (VOID **) &pOssInfo)) { hr = HError(); printf("OssInfoDecodeAndAlloc returned %u (%x)\n", hr, hr); goto error; } lRemainExtra = (LONG) *pcbInfo - INFO_LEN_ALIGN(sizeof(*pcgi)); pbExtra = NULL; // for lRemainExtra < 0, LENGTH_ONLY calculation if (0 <= lRemainExtra) { pcgi = (CERT_KEYGEN_REQUEST_INFO *) pInfo; // Default all optional fields to zero ZeroMemory((VOID *) pcgi, sizeof(*pcgi)); pcgi->dwVersion = 1; pbExtra = (BYTE *) pcgi + INFO_LEN_ALIGN(sizeof(*pcgi)); } OssX509GetPublicKeyInfo( &pOssInfo->publicKeyAndChallenge.spki, dwFlags, &pcgi->SubjectPublicKeyInfo, &pbExtra, &lRemainExtra); OssX509GetIA5ConvertedToUnicode( &pOssInfo->publicKeyAndChallenge.challenge, dwFlags, &pcgi->pwszChallengeString, &pbExtra, &lRemainExtra); if (0 <= lRemainExtra) { *pcbInfo = *pcbInfo - (DWORD) lRemainExtra; } else { *pcbInfo = *pcbInfo + (DWORD) -lRemainExtra; if (NULL != pInfo) { SetLastError(HRESULT_FROM_WIN32(ERROR_MORE_DATA)); goto error; } } fResult = TRUE; error: OssInfoFree(SignedPublicKeyAndChallenge_PDU, pOssInfo); if (!fResult) { *pcbInfo = 0; } return(fResult); } #endif BOOL myDecodeKeyGenRequest( IN BYTE const *pbRequest, IN DWORD cbRequest, OUT CERT_KEYGEN_REQUEST_INFO **ppKeyGenRequest, OUT DWORD *pcbKeyGenRequest) { BOOL fOk = FALSE; #ifdef CRYPT32_SP3_ONLY *ppKeyGenRequest = NULL; *pcbKeyGenRequest = 0; if (!DecodeKeyGen( pbRequest, cbRequest, 0, // dwFlags NULL, pcbKeyGenRequest)) { goto error; } *ppKeyGenRequest = (CERT_KEYGEN_REQUEST_INFO *) LocalAlloc(LMEM_FIXED, *pcbKeyGenRequest); if (NULL == *ppKeyGenRequest) { _PrintError(E_OUTOFMEMORY, "LocalAlloc(KeyGenRequest)"); SetLastError(E_OUTOFMEMORY); goto error; } if (!DecodeKeyGen( pbRequest, cbRequest, 0, // dwFlags *ppKeyGenRequest, pcbKeyGenRequest)) { goto error; } #else if (!myDecodeObject( X509_ASN_ENCODING, X509_KEYGEN_REQUEST_TO_BE_SIGNED, pbRequest, cbRequest, (VOID **) ppKeyGenRequest, pcbKeyGenRequest)) { err = myHLastError(); _JumpError(err, error, "myDecodeObject"); } #endif fOk = TRUE; error: return(fOk); }