windows-nt/Source/XPSP1/NT/ds/security/csps/gemsafe/gemcomp/compcert.c
2020-09-26 16:20:57 +08:00

5890 lines
188 KiB
C

/*******************************************************************************
* Copyright (c) 1998 Gemplus Development
*
* Name : COMPCERT.C
*
* Description : Programme de compression de certificat X.509
*
* Author : Christophe Clavier
*
* Modify : Laurent CASSIER
*
* Compiler : Microsoft Visual C 5.0
*
* Host : IBM PC and compatible machines under Windows 95.
*
* Release : 1.10.001
*
* Last Modif : 04/03/98: V1.10.001 - Change dictionary management and add
* CC_Init(), CC_Exit() functions.
* 30/01/98: V1.00.005 - Cancel (_OPT_HEADER) the modification in
* the length of subjectPKInfo and signature
* made in the previous version.
* 28/01/98: V1.00.004 - Allows up to 32767 entries in the dictionary
* and stores the length of the subjectPKInfo
* and signature on one byte instead of two if
* it is less than 128.
* 13/01/98: V1.00.003 - Modify for meta-compression and dictionary
* version ascending compatibility.
* 11/12/97: V1.00.002 - Modify for new dictionary format
* and compatible with CSP and PKCS.
* 27/08/97: V1.00.001 - First implementation.
*
********************************************************************************
*
* Warning :
*
* Remark : Flags de compilations :
*
* - _STUDY : Lorsqu'il est défini, des fichiers de log utiles
* lors de l'étude de l'efficacité des algos
* de compression. sont générés.
*
* - _TRICKY_COMPRESSION : Lorsqu'il est défini, on ne tente pas
* de compresser les champs
* 'subjectPublicKey' et 'signature' qui
* sont essentiellement aléatoires.
*
* - _OPT_HEADER : Lorsqu'il est défini, et si _TRICKY_COMPRESSION
* est défini également, le header de longueur des
* compressés de subjectPKInfo et de signature
* sont optimisés pour ne tenir sur un seul octet
* si la longueur est inférieure à 128 au lieu de
* deux octets dans tous les cas sinon.
* Ne pas définir ce flag permet d'être compatible
* avec les versions inférieures à 1.00.005
*
* - _GLOBAL_COMPRESSION : Lorsqu'il est défini, le compressé du
* certificat est lui même envoyé à la
* fonction CC_RawEncode afin d'y appliquer
* le meilleur algo de compression dispo.
*
* - _OPT_HEADER : Lorsqu'il est défini, l
* certificat est lui même envoyé à la
* fonction CC_RawEncode afin d'y appliquer
* le meilleur algo de compression dispo.
*
* - _ALGO_x (x de 1 à 7) : Lorsqu'il est défini, l'algo de
* compression numéro x est utilisé.
*
* Conseils pour la version release de GemPASS :
*
* - _STUDY : non défini
* - _TRICKY_COMPRESSION : défini
* - _OPT_HEADER : non défini
* - _GLOBAL_COMPRESSION : non défini
* - _ALGO_1 : défini
* - _ALGO_2 : défini
* - _ALGO_x (x>2) : non défini
*
*******************************************************************************/
/*------------------------------------------------------------------------------
Includes files
------------------------------------------------------------------------------*/
#ifdef _WINDOWS
#include <windows.h>
#endif
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "ccdef.h"
#include "ac.h"
#include "compcert.h"
#include "gmem.h"
#include "resource.h"
extern HINSTANCE g_hInstRes;
/*------------------------------------------------------------------------------
Information section
------------------------------------------------------------------------------*/
#define G_NAME "COMPCERT"
#define G_RELEASE "1.10.001"
/*------------------------------------------------------------------------------
Static Variables
------------------------------------------------------------------------------*/
USHORT NbDaysInMonth[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
char* AlgorithmTypeDict[] = {
/* x9-57 */
"\x2A\x86\x48\xCE\x38\x02\x01", /*x9.57-holdinstruction-none (1 2 840 10040 2 1) */
"\x2A\x86\x48\xCE\x38\x02\x02", /*x9.57-holdinstruction-callissuer (1 2 840 10040 2 2) */
"\x2A\x86\x48\xCE\x38\x02\x03", /*x9.57-holdinstruction-reject (1 2 840 10040 2 3) */
"\x2A\x86\x48\xCE\x38\x04\x01", /*x9.57-dsa (1 2 840 10040 4 1) */
"\x2A\x86\x48\xCE\x38\x04\x03", /*x9.57-dsaWithSha1 (1 2 840 10040 4 3) */
/* x9-42 */
"\x2A\x86\x48\xCE\x3E\x02\x01", /*x9.42-dhPublicNumber (1 2 840 10046 2 1) */
/* Nortel Secure Networks */
"\x2A\x86\x48\x86\xF6\x7D\x07\x42", /*nsn-alg (1 2 840 113533 7 66) */
"\x2A\x86\x48\x86\xF6\x7D\x07\x42\x0A", /*nsn-alg-cast5CBC (1 2 840 113533 7 66 10) */
"\x2A\x86\x48\x86\xF6\x7D\x07\x42\x0B", /*nsn-alg-cast5MAC (1 2 840 113533 7 66 11) */
"\x2A\x86\x48\x86\xF6\x7D\x07\x42\x0C", /*nsn-alg-pbeWithMD5AndCAST5-CBC (1 2 840 113533 7 66 12) */
/* PKCS #1 */
"\x2A\x86\x48\x86\xF7\x0D\x01\x01", /*pkcs-1 (1 2 840 113549 1 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01", /*pkcs-1-rsaEncryption (1 2 840 113549 1 1 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x02", /*pkcs-1-MD2withRSAEncryption (1 2 840 113549 1 1 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x03", /*pkcs-1-MD4withRSAEncryption (1 2 840 113549 1 1 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04", /*pkcs-1-MD5withRSAEncryption (1 2 840 113549 1 1 4) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05", /*pkcs-1-SHA1withRSAEncryption (1 2 840 113549 1 1 5) */
/*need to determine which of the following 2 is correct */
/*"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x06", pkcs-1-ripemd160WithRSAEncryption (1 2 840 113549 1 1 6) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x06", /*pkcs-1-rsaOAEPEncryptionSET (1 2 840 113549 1 1 6) */
/* PKCS #3 */
"\x2A\x86\x48\x86\xF7\x0D\x01\x03", /*pkcs-3 (1 2 840 113549 1 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x03\x01", /*pkcs-3-dhKeyAgreement (1 2 840 113549 1 3 1) */
/* PKCS #5 */
"\x2A\x86\x48\x86\xF7\x0D\x01\x05", /*pkcs-5 (1 2 840 113549 1 5) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x05\x01", /*pkcs-5-pbeWithMD2AndDES-CBC (1 2 840 113549 1 5 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x05\x03", /*pkcs-5-pbeWithMD5AndDES-CBC (1 2 840 113549 1 5 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x05\x04", /*pkcs-5-pbeWithMD2AndRC2-CBC (1 2 840 113549 1 5 4) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x05\x06", /*pkcs-5-pbeWithMD5AndRC2-CBC (1 2 840 113549 1 5 6) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x05\x09", /*pkcs-5-pbeWithMD5AndXOR (1 2 840 113549 1 5 9) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x05\x0A", /*pkcs-5-pbeWithSHA1AndDES-CBC (1 2 840 113549 1 5 10) */
/* PKCS #12 */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C", /*pkcs-12 (1 2 840 113549 1 12) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x01", /*pkcs-12-modeID (1 2 840 113549 1 12 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x01\x01", /*pkcs-12-OfflineTransportMode (1 2 840 113549 1 12 1 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x01\x02", /*pkcs-12-OnlineTransportMode (1 2 840 113549 1 12 1 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x02", /*pkcs-12-ESPVKID (1 2 840 113549 1 12 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x02\x01", /*pkcs-12-PKCS8KeyShrouding (1 2 840 113549 1 12 2 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x03", /*pkcs-12-BagID (1 2 840 113549 1 12 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x03\x01", /*pkcs-12-KeyBagID (1 2 840 113549 1 12 3 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x03\x02", /*pkcs-12-CertAndCRLBagID (1 2 840 113549 1 12 3 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x03\x03", /*pkcs-12-SecretBagID (1 2 840 113549 1 12 3 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x04", /*pkcs-12-CertBagID (1 2 840 113549 1 12 4) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x04\x01", /*pkcs-12-X509CertCRLBag (1 2 840 113549 1 12 4 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x04\x02", /*pkcs-12-SDSICertBag (1 2 840 113549 1 12 4 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05", /*pkcs-12-OID (1 2 840 113549 1 12 5) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01", /*pkcs-12-PBEID (1 2 840 113549 1 12 5 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01\x01", /*pkcs-12-PBEWithSha1And128BitRC4 (1 2 840 113549 1 12 5 1 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01\x02", /*pkcs-12-PBEWithSha1And40BitRC4 (1 2 840 113549 1 12 5 1 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01\x03", /*pkcs-12-PBEWithSha1AndTripleDESCBC (1 2 840 113549 1 12 5 1 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01\x04", /*pkcs-12-PBEWithSha1And128BitRC2CBC (1 2 840 113549 1 12 5 1 4) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01\x05", /*pkcs-12-PBEWithSha1And40BitRC2CBC (1 2 840 113549 1 12 5 1 5) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01\x06", /*pkcs-12-PBEWithSha1AndRC4 (1 2 840 113549 1 12 5 1 6) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01\x07", /*pkcs-12-PBEWithSha1AndRC2CBC (1 2 840 113549 1 12 5 1 7) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x02", /*pkcs-12-EnvelopingID (1 2 840 113549 1 12 5 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x02\x01", /*pkcs-12-RSAEncryptionWith128BitRC4 (1 2 840 113549 1 12 5 2 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x02\x02", /*pkcs-12-RSAEncryptionWith40BitRC4 (1 2 840 113549 1 12 5 2 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x02\x03", /*pkcs-12-RSAEncryptionWithTripleDES (1 2 840 113549 1 12 5 2 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x03", /*pkcs-12-SignatureID (1 2 840 113549 1 12 5 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x03\x01", /*pkcs-12-RSASignatureWithSHA1Digest (1 2 840 113549 1 12 5 3 1) */
/* RSADSI digest algorithms */
"\x2A\x86\x48\x86\xF7\x0D\x02", /*RSADSI-digestAlgorithm (1 2 840 113549 2) */
"\x2A\x86\x48\x86\xF7\x0D\x02\x02", /*RSADSI-md2 (1 2 840 113549 2 2) */
"\x2A\x86\x48\x86\xF7\x0D\x02\x04", /*RSADSI-md4 (1 2 840 113549 2 4) */
"\x2A\x86\x48\x86\xF7\x0D\x02\x05", /*RSADSI-md5 (1 2 840 113549 2 5) */
/* RSADSI encryption algorithms */
"\x2A\x86\x48\x86\xF7\x0D\x03", /*RSADSI-encryptionAlgorithm (1 2 840 113549 3) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x02", /*RSADSI-rc2CBC (1 2 840 113549 3 2) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x03", /*RSADSI-rc2ECB (1 2 840 113549 3 3) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x04", /*RSADSI-rc4 (1 2 840 113549 3 4) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x05", /*RSADSI-rc4WithMAC (1 2 840 113549 3 5) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x06", /*RSADSI-DESX-CBC (1 2 840 113549 3 6) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x07", /*RSADSI-DES-EDE3-CBC (1 2 840 113549 3 7) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x08", /*RSADSI-RC5CBC (1 2 840 113549 3 8) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x09", /*RSADSI-RC5CBCPad (1 2 840 113549 3 9) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x0A", /*RSADSI-CDMFCBCPad (1 2 840 113549 3 10) */
/* cryptlib */
"\x2B\x06\x01\x04\x01\x97\x55\x20\x01", /*cryptlibEnvelope (1 3 6 1 4 1 3029 32 1) */
/* Not sure about these ones: */
/*"\x2B\x0E\x02\x1A\x05", sha (1 3 14 2 26 5) */
/*"\x2B\x0E\x03\x02\x01\x01", rsa (1 3 14 3 2 1 1) */ //X-509
/*"\x2B\x0E\x03\x02\x02\x01", sqmod-N (1 3 14 3 2 2 1) */ //X-509
/*"\x2B\x0E\x03\x02\x03\x01", sqmod-NwithRSA (1 3 14 3 2 3 1) */ //X-509
/* Miscellaneous partially-defunct OIW semi-standards aka algorithms */
"\x2B\x0E\x03\x02\x02", /*ISO-algorithm-md4WitRSA (1 3 14 3 2 2) */
"\x2B\x0E\x03\x02\x03", /*ISO-algorithm-md5WithRSA (1 3 14 3 2 3) */
"\x2B\x0E\x03\x02\x04", /*ISO-algorithm-md4WithRSAEncryption (1 3 14 3 2 4) */
"\x2B\x0E\x03\x02\x06", /*ISO-algorithm-desECB (1 3 14 3 2 6) */
"\x2B\x0E\x03\x02\x07", /*ISO-algorithm-desCBC (1 3 14 3 2 7) */
"\x2B\x0E\x03\x02\x08", /*ISO-algorithm-desOFB (1 3 14 3 2 8) */
"\x2B\x0E\x03\x02\x09", /*ISO-algorithm-desCFB (1 3 14 3 2 9) */
"\x2B\x0E\x03\x02\x0A", /*ISO-algorithm-desMAC (1 3 14 3 2 10) */
"\x2B\x0E\x03\x02\x0B", /*ISO-algorithm-rsaSignature (1 3 14 3 2 11) */ //ISO 9796
"\x2B\x0E\x03\x02\x0C", /*ISO-algorithm-dsa (1 3 14 3 2 12) */
"\x2B\x0E\x03\x02\x0D", /*ISO-algorithm-dsaWithSHA (1 3 14 3 2 13) */
"\x2B\x0E\x03\x02\x0E", /*ISO-algorithm-mdc2WithRSASignature (1 3 14 3 2 14) */
"\x2B\x0E\x03\x02\x0F", /*ISO-algorithm-shaWithRSASignature (1 3 14 3 2 15) */
"\x2B\x0E\x03\x02\x10", /*ISO-algorithm-dhWithCommonModulus (1 3 14 3 2 16) */
"\x2B\x0E\x03\x02\x11", /*ISO-algorithm-desEDE (1 3 14 3 2 17) */
"\x2B\x0E\x03\x02\x12", /*ISO-algorithm-sha (1 3 14 3 2 18) */
"\x2B\x0E\x03\x02\x13", /*ISO-algorithm-mdc-2 (1 3 14 3 2 19) */
"\x2B\x0E\x03\x02\x14", /*ISO-algorithm-dsaCommon (1 3 14 3 2 20) */
"\x2B\x0E\x03\x02\x15", /*ISO-algorithm-dsaCommonWithSHA (1 3 14 3 2 21) */
"\x2B\x0E\x03\x02\x16", /*ISO-algorithm-rsaKeyTransport (1 3 14 3 2 22) */
"\x2B\x0E\x03\x02\x17", /*ISO-algorithm-keyed-hash-seal (1 3 14 3 2 23) */
"\x2B\x0E\x03\x02\x18", /*ISO-algorithm-md2WithRSASignature (1 3 14 3 2 24) */
"\x2B\x0E\x03\x02\x19", /*ISO-algorithm-md5WithRSASignature (1 3 14 3 2 25) */
"\x2B\x0E\x03\x02\x1A", /*ISO-algorithm-sha1 (1 3 14 3 2 26) */
"\x2B\x0E\x03\x02\x1B", /*ISO-algorithm-ripemd160 (1 3 14 3 2 27) */
"\x2B\x0E\x03\x02\x1D", /*ISO-algorithm-sha-1WithRSAEncryption (1 3 14 3 2 29) */
"\x2B\x0E\x03\x03\x01", /*ISO-algorithm-simple-strong-auth-mechanism (1 3 14 3 3 1) */
/* Not sure about these ones:
/*"\x2B\x0E\x07\x02\x01\x01", ElGamal (1 3 14 7 2 1 1) */
/*"\x2B\x0E\x07\x02\x03\x01", md2WithRSA (1 3 14 7 2 3 1) */
/*"\x2B\x0E\x07\x02\x03\x02", md2WithElGamal (1 3 14 7 2 3 2) */
/* X500 algorithms */
"\x55\x08", /*X500-Algorithms (2 5 8) */
"\x55\x08\x01", /*X500-Alg-Encryption (2 5 8 1) */
"\x55\x08\x01\x01", /*rsa (2 5 8 1 1) */
/* DMS-SDN-702 */
"\x60\x86\x48\x01\x65\x02\x01\x01\x01", /*id-sdnsSignatureAlgorithm (2 16 840 1 101 2 1 1 1) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x02", /*id-mosaicSignatureAlgorithm (2 16 840 1 101 2 1 1 2) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x03", /*id-sdnsConfidentialityAlgorithm (2 16 840 1 101 2 1 1 3) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x04", /*id-mosaicConfidentialityAlgorithm (2 16 840 1 101 2 1 1 4) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x05", /*id-sdnsIntegrityAlgorithm (2 16 840 1 101 2 1 1 5) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x06", /*id-mosaicIntegrityAlgorithm (2 16 840 1 101 2 1 1 6) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x07", /*id-sdnsTokenProtectionAlgorithm (2 16 840 1 101 2 1 1 7) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x08", /*id-mosaicTokenProtectionAlgorithm (2 16 840 1 101 2 1 1 8) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x09", /*id-sdnsKeyManagementAlgorithm (2 16 840 1 101 2 1 1 9) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x0A", /*id-mosaicKeyManagementAlgorithm (2 16 840 1 101 2 1 1 10) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x0B", /*id-sdnsKMandSigAlgorithm (2 16 840 1 101 2 1 1 11) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x0C", /*id-mosaicKMandSigAlgorithm (2 16 840 1 101 2 1 1 12) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x0D", /*id-SuiteASignatureAlgorithm (2 16 840 1 101 2 1 1 13) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x0E", /*id-SuiteAConfidentialityAlgorithm (2 16 840 1 101 2 1 1 14) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x0F", /*id-SuiteAIntegrityAlgorithm (2 16 840 1 101 2 1 1 15) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x10", /*id-SuiteATokenProtectionAlgorithm (2 16 840 1 101 2 1 1 16) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x11", /*id-SuiteAKeyManagementAlgorithm (2 16 840 1 101 2 1 1 17) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x12", /*id-SuiteAKMandSigAlgorithm (2 16 840 1 101 2 1 1 18) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x13", /*id-mosaicUpdatedSigAlgorithm (2 16 840 1 101 2 1 1 19) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x14", /*id-mosaicKMandUpdSigAlgorithms (2 16 840 1 101 2 1 1 20) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x15", /*id-mosaicUpdatedIntegAlgorithm (2 16 840 1 101 2 1 1 21) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x16", /*id-mosaicKeyEncryptionAlgorithm (2 16 840 1 101 2 1 1 22) */
NULL
};
char* AttributeTypeDict[] = {
/* x9-57 */
"\x2A\x86\x48\xCE\x38\x02\x01", /*x9.57-holdinstruction-none (1 2 840 10040 2 1) */
"\x2A\x86\x48\xCE\x38\x02\x02", /*x9.57-holdinstruction-callissuer (1 2 840 10040 2 2) */
"\x2A\x86\x48\xCE\x38\x02\x03", /*x9.57-holdinstruction-reject (1 2 840 10040 2 3) */
"\x2A\x86\x48\xCE\x38\x04\x01", /*x9.57-dsa (1 2 840 10040 4 1) */
"\x2A\x86\x48\xCE\x38\x04\x03", /*x9.57-dsaWithSha1 (1 2 840 10040 4 3) */
/* x9-42 */
"\x2A\x86\x48\xCE\x3E\x02\x01", /*x9.42-dhPublicNumber (1 2 840 10046 2 1) */
/* Nortel Secure Networks */
"\x2A\x86\x48\x86\xF6\x7D\x07", /*nsn (1 2 840 113533 7) */
"\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00", /*nsn-ce-entrustVersInfo (1 2 840 113533 7 65 0) */
"\x2A\x86\x48\x86\xF6\x7D\x07\x41", /*nsn-ce (1 2 840 113533 7 65) */
"\x2A\x86\x48\x86\xF6\x7D\x07\x42", /*nsn-alg (1 2 840 113533 7 66) */
"\x2A\x86\x48\x86\xF6\x7D\x07\x42\x0A", /*nsn-alg-cast5CBC (1 2 840 113533 7 66 10) */
"\x2A\x86\x48\x86\xF6\x7D\x07\x42\x0B", /*nsn-alg-cast5MAC (1 2 840 113533 7 66 11) */
"\x2A\x86\x48\x86\xF6\x7D\x07\x42\x0C", /*nsn-alg-pbeWithMD5AndCAST5-CBC (1 2 840 113533 7 66 12) */
"\x2A\x86\x48\x86\xF6\x7D\x07\x43", /*nsn-oc (1 2 840 113533 7 67) */
"\x2A\x86\x48\x86\xF6\x7D\x07\x43\x0C", /*nsn-oc-entrustUser (1 2 840 113533 7 67 0) */
"\x2A\x86\x48\x86\xF6\x7D\x07\x44\x00", /*nsn-at-entrustCAInfo (1 2 840 113533 7 68 0) */
"\x2A\x86\x48\x86\xF6\x7D\x07\x44\x0A", /*nsn-at-attributeCertificate (1 2 840 113533 7 68 10) */
"\x2A\x86\x48\x86\xF6\x7D\x07\x44", /*nsn-at (1 2 840 113533 7 68) */
/* PKCS #1 */
"\x2A\x86\x48\x86\xF7\x0D\x01\x01", /*pkcs-1 (1 2 840 113549 1 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01", /*pkcs-1-rsaEncryption (1 2 840 113549 1 1 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x02", /*pkcs-1-MD2withRSAEncryption (1 2 840 113549 1 1 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x03", /*pkcs-1-MD4withRSAEncryption (1 2 840 113549 1 1 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04", /*pkcs-1-MD5withRSAEncryption (1 2 840 113549 1 1 4) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05", /*pkcs-1-SHA1withRSAEncryption (1 2 840 113549 1 1 5) */
/*need to determine which of the following 2 is correct */
/*"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x06", pkcs-1-ripemd160WithRSAEncryption (1 2 840 113549 1 1 6) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x06", /*pkcs-1-rsaOAEPEncryptionSET (1 2 840 113549 1 1 6) */
/* PKCS #3 */
"\x2A\x86\x48\x86\xF7\x0D\x01\x03", /*pkcs-3 (1 2 840 113549 1 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x03\x01", /*pkcs-3-dhKeyAgreement (1 2 840 113549 1 3 1) */
/* PKCS #5 */
"\x2A\x86\x48\x86\xF7\x0D\x01\x05", /*pkcs-5 (1 2 840 113549 1 5) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x05\x01", /*pkcs-5-pbeWithMD2AndDES-CBC (1 2 840 113549 1 5 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x05\x03", /*pkcs-5-pbeWithMD5AndDES-CBC (1 2 840 113549 1 5 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x05\x04", /*pkcs-5-pbeWithMD2AndRC2-CBC (1 2 840 113549 1 5 4) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x05\x06", /*pkcs-5-pbeWithMD5AndRC2-CBC (1 2 840 113549 1 5 6) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x05\x09", /*pkcs-5-pbeWithMD5AndXOR (1 2 840 113549 1 5 9) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x05\x0A", /*pkcs-5-pbeWithSHA1AndDES-CBC (1 2 840 113549 1 5 10) */
/* PKCS #7 */
"\x2A\x86\x48\x86\xF7\x0D\x01\x07", /*pkcs-7 (1 2 840 113549 1 7) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x07\x01", /*pkcs-7-data (1 2 840 113549 1 7 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x07\x02", /*pkcs-7-signedData (1 2 840 113549 1 7 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x07\x03", /*pkcs-7-envelopedData (1 2 840 113549 1 7 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x07\x04", /*pkcs-7-signedAndEnvelopedData (1 2 840 113549 1 7 4) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x07\x05", /*pkcs-7-digestData (1 2 840 113549 1 7 5) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x07\x06", /*pkcs-7-encryptedData (1 2 840 113549 1 7 6) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x07\x07", /*pkcs-7-dataWithAttributes (1 2 840 113549 1 7 7) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x07\x08", /*pkcs-7-encryptedPrivateKeyInfo (1 2 840 113549 1 7 8) */
/* PKCS #9 */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09", /*pkcs-9 (1 2 840 113549 1 9) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01", /*pkcs-9-emailAddress (1 2 840 113549 1 9 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09\x02", /*pkcs-9-unstructuredName (1 2 840 113549 1 9 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09\x03", /*pkcs-9-contentType (1 2 840 113549 1 9 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09\x04", /*pkcs-9-messageDigest (1 2 840 113549 1 9 4) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09\x05", /*pkcs-9-signingTime (1 2 840 113549 1 9 5) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09\x06", /*pkcs-9-countersignature (1 2 840 113549 1 9 6) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09\x07", /*pkcs-9-challengePassword (1 2 840 113549 1 9 7) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09\x08", /*pkcs-9-unstructuredAddress (1 2 840 113549 1 9 8) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09\x09", /*pkcs-9-extendedCertificateAttributes (1 2 840 113549 1 9 9) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09\x0A", /*pkcs-9-issuerAndSerialNumber (1 2 840 113549 1 9 10) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09\x0B", /*pkcs-9-passwordCheck (1 2 840 113549 1 9 11) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09\x0C", /*pkcs-9-publicKey (1 2 840 113549 1 9 12) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09\x0D", /*pkcs-9-signingDescription (1 2 840 113549 1 9 13) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09\x0E", /*pkcs-9-X.509 extension (1 2 840 113549 1 9 14) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x09\x0F", /*pkcs-9-SMIMECapabilities (1 2 840 113549 1 9 15) */
/* PKCS #12 */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C", /*pkcs-12 (1 2 840 113549 1 12) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x01", /*pkcs-12-modeID (1 2 840 113549 1 12 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x01\x01", /*pkcs-12-OfflineTransportMode (1 2 840 113549 1 12 1 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x01\x02", /*pkcs-12-OnlineTransportMode (1 2 840 113549 1 12 1 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x02", /*pkcs-12-ESPVKID (1 2 840 113549 1 12 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x02\x01", /*pkcs-12-PKCS8KeyShrouding (1 2 840 113549 1 12 2 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x03", /*pkcs-12-BagID (1 2 840 113549 1 12 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x03\x01", /*pkcs-12-KeyBagID (1 2 840 113549 1 12 3 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x03\x02", /*pkcs-12-CertAndCRLBagID (1 2 840 113549 1 12 3 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x03\x03", /*pkcs-12-SecretBagID (1 2 840 113549 1 12 3 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x04", /*pkcs-12-CertBagID (1 2 840 113549 1 12 4) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x04\x01", /*pkcs-12-X509CertCRLBag (1 2 840 113549 1 12 4 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x04\x02", /*pkcs-12-SDSICertBag (1 2 840 113549 1 12 4 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05", /*pkcs-12-OID (1 2 840 113549 1 12 5) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01", /*pkcs-12-PBEID (1 2 840 113549 1 12 5 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01\x01", /*pkcs-12-PBEWithSha1And128BitRC4 (1 2 840 113549 1 12 5 1 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01\x02", /*pkcs-12-PBEWithSha1And40BitRC4 (1 2 840 113549 1 12 5 1 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01\x03", /*pkcs-12-PBEWithSha1AndTripleDESCBC (1 2 840 113549 1 12 5 1 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01\x04", /*pkcs-12-PBEWithSha1And128BitRC2CBC (1 2 840 113549 1 12 5 1 4) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01\x05", /*pkcs-12-PBEWithSha1And40BitRC2CBC (1 2 840 113549 1 12 5 1 5) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01\x06", /*pkcs-12-PBEWithSha1AndRC4 (1 2 840 113549 1 12 5 1 6) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x01\x07", /*pkcs-12-PBEWithSha1AndRC2CBC (1 2 840 113549 1 12 5 1 7) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x02", /*pkcs-12-EnvelopingID (1 2 840 113549 1 12 5 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x02\x01", /*pkcs-12-RSAEncryptionWith128BitRC4 (1 2 840 113549 1 12 5 2 1) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x02\x02", /*pkcs-12-RSAEncryptionWith40BitRC4 (1 2 840 113549 1 12 5 2 2) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x02\x03", /*pkcs-12-RSAEncryptionWithTripleDES (1 2 840 113549 1 12 5 2 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x03", /*pkcs-12-SignatureID (1 2 840 113549 1 12 5 3) */
"\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x05\x03\x01", /*pkcs-12-RSASignatureWithSHA1Digest (1 2 840 113549 1 12 5 3 1) */
/* RSADSI digest algorithms */
"\x2A\x86\x48\x86\xF7\x0D\x02", /*RSADSI-digestAlgorithm (1 2 840 113549 2) */
"\x2A\x86\x48\x86\xF7\x0D\x02\x02", /*RSADSI-md2 (1 2 840 113549 2 2) */
"\x2A\x86\x48\x86\xF7\x0D\x02\x04", /*RSADSI-md4 (1 2 840 113549 2 4) */
"\x2A\x86\x48\x86\xF7\x0D\x02\x05", /*RSADSI-md5 (1 2 840 113549 2 5) */
/* RSADSI encryption algorithms */
"\x2A\x86\x48\x86\xF7\x0D\x03", /*RSADSI-encryptionAlgorithm (1 2 840 113549 3) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x02", /*RSADSI-rc2CBC (1 2 840 113549 3 2) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x03", /*RSADSI-rc2ECB (1 2 840 113549 3 3) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x04", /*RSADSI-rc4 (1 2 840 113549 3 4) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x05", /*RSADSI-rc4WithMAC (1 2 840 113549 3 5) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x06", /*RSADSI-DESX-CBC (1 2 840 113549 3 6) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x07", /*RSADSI-DES-EDE3-CBC (1 2 840 113549 3 7) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x08", /*RSADSI-RC5CBC (1 2 840 113549 3 8) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x09", /*RSADSI-RC5CBCPad (1 2 840 113549 3 9) */
"\x2A\x86\x48\x86\xF7\x0D\x03\x0A", /*RSADSI-CDMFCBCPad (1 2 840 113549 3 10) */
/* Microsoft OIDs */
"\x2A\x86\x48\x86\xF7\x14\x04\x03", /*microsoftExcel (1 2 840 113556 4 3) */
"\x2A\x86\x48\x86\xF7\x14\x04\x04", /*titledWithOID (1 2 840 113556 4 4) */
"\x2A\x86\x48\x86\xF7\x14\x04\x05", /*microsoftPowerPoint (1 2 840 113556 4 5) */
/* cryptlib */
"\x2B\x06\x01\x04\x01\x97\x55\x20\x01", /*cryptlibEnvelope (1 3 6 1 4 1 3029 32 1) */
/* PKIX */
"\x2B\x06\x01\x05\x05\x07", /*pkix-oid (1 3 6 1 5 5 7) */
"\x2B\x06\x01\x05\x05\x07\x01", /*pkix-subjectInfoAccess (1 3 6 1 5 5 7 1) */
"\x2B\x06\x01\x05\x05\x07\x02", /*pkix-authorityInfoAccess (1 3 6 1 5 5 7 2) */
"\x2B\x06\x01\x05\x05\x07\x04", /*pkix-cps (1 3 6 1 5 5 7 4) */
"\x2B\x06\x01\x05\x05\x07\x05", /*pkix-userNotice (1 3 6 1 5 5 7 5) */
/* Not sure about these ones: */
/*"\x2B\x0E\x02\x1A\x05", sha (1 3 14 2 26 5) */
/*"\x2B\x0E\x03\x02\x01\x01", rsa (1 3 14 3 2 1 1) */ //X-509
/*"\x2B\x0E\x03\x02\x02\x01", sqmod-N (1 3 14 3 2 2 1) */ //X-509
/*"\x2B\x0E\x03\x02\x03\x01", sqmod-NwithRSA (1 3 14 3 2 3 1) */ //X-509
/* Miscellaneous partially-defunct OIW semi-standards aka algorithms */
"\x2B\x0E\x03\x02\x02", /*ISO-algorithm-md4WitRSA (1 3 14 3 2 2) */
"\x2B\x0E\x03\x02\x03", /*ISO-algorithm-md5WithRSA (1 3 14 3 2 3) */
"\x2B\x0E\x03\x02\x04", /*ISO-algorithm-md4WithRSAEncryption (1 3 14 3 2 4) */
"\x2B\x0E\x03\x02\x06", /*ISO-algorithm-desECB (1 3 14 3 2 6) */
"\x2B\x0E\x03\x02\x07", /*ISO-algorithm-desCBC (1 3 14 3 2 7) */
"\x2B\x0E\x03\x02\x08", /*ISO-algorithm-desOFB (1 3 14 3 2 8) */
"\x2B\x0E\x03\x02\x09", /*ISO-algorithm-desCFB (1 3 14 3 2 9) */
"\x2B\x0E\x03\x02\x0A", /*ISO-algorithm-desMAC (1 3 14 3 2 10) */
"\x2B\x0E\x03\x02\x0B", /*ISO-algorithm-rsaSignature (1 3 14 3 2 11) */ //ISO 9796
"\x2B\x0E\x03\x02\x0C", /*ISO-algorithm-dsa (1 3 14 3 2 12) */
"\x2B\x0E\x03\x02\x0D", /*ISO-algorithm-dsaWithSHA (1 3 14 3 2 13) */
"\x2B\x0E\x03\x02\x0E", /*ISO-algorithm-mdc2WithRSASignature (1 3 14 3 2 14) */
"\x2B\x0E\x03\x02\x0F", /*ISO-algorithm-shaWithRSASignature (1 3 14 3 2 15) */
"\x2B\x0E\x03\x02\x10", /*ISO-algorithm-dhWithCommonModulus (1 3 14 3 2 16) */
"\x2B\x0E\x03\x02\x11", /*ISO-algorithm-desEDE (1 3 14 3 2 17) */
"\x2B\x0E\x03\x02\x12", /*ISO-algorithm-sha (1 3 14 3 2 18) */
"\x2B\x0E\x03\x02\x13", /*ISO-algorithm-mdc-2 (1 3 14 3 2 19) */
"\x2B\x0E\x03\x02\x14", /*ISO-algorithm-dsaCommon (1 3 14 3 2 20) */
"\x2B\x0E\x03\x02\x15", /*ISO-algorithm-dsaCommonWithSHA (1 3 14 3 2 21) */
"\x2B\x0E\x03\x02\x16", /*ISO-algorithm-rsaKeyTransport (1 3 14 3 2 22) */
"\x2B\x0E\x03\x02\x17", /*ISO-algorithm-keyed-hash-seal (1 3 14 3 2 23) */
"\x2B\x0E\x03\x02\x18", /*ISO-algorithm-md2WithRSASignature (1 3 14 3 2 24) */
"\x2B\x0E\x03\x02\x19", /*ISO-algorithm-md5WithRSASignature (1 3 14 3 2 25) */
"\x2B\x0E\x03\x02\x1A", /*ISO-algorithm-sha1 (1 3 14 3 2 26) */
"\x2B\x0E\x03\x02\x1B", /*ISO-algorithm-ripemd160 (1 3 14 3 2 27) */
"\x2B\x0E\x03\x02\x1D", /*ISO-algorithm-sha-1WithRSAEncryption (1 3 14 3 2 29) */
"\x2B\x0E\x03\x03\x01", /*ISO-algorithm-simple-strong-auth-mechanism (1 3 14 3 3 1) */
/* Not sure about these ones:
/*"\x2B\x0E\x07\x02\x01\x01", ElGamal (1 3 14 7 2 1 1) */
/*"\x2B\x0E\x07\x02\x03\x01", md2WithRSA (1 3 14 7 2 3 1) */
/*"\x2B\x0E\x07\x02\x03\x02", md2WithElGamal (1 3 14 7 2 3 2) */
/* X.520 id-at = 2 5 4*/
"\x55\x04\x00", /*X.520-at-objectClass (2 5 4 0) */
"\x55\x04\x01", /*X.520-at-aliasObjectName (2 5 4 1) */
"\x55\x04\x02", /*X.520-at-knowledgeInformation (2 5 4 2) */
"\x55\x04\x03", /*X.520-at-commonName (2 5 4 3) */
"\x55\x04\x04", /*X.520-at-surname (2 5 4 4) */
"\x55\x04\x05", /*X.520-at-serialNumber (2 5 4 5) */
"\x55\x04\x06", /*X.520-at-countryName (2 5 4 6) */
"\x55\x04\x07", /*X.520-at-localityName (2 5 4 7) */
"\x55\x04\x08", /*X.520-at-stateOrProvinceName (2 5 4 8) */
"\x55\x04\x09", /*X.520-at-streetAddress (2 5 4 9) */
"\x55\x04\x0A", /*X.520-at-organizationName (2 5 4 10) */
"\x55\x04\x0B", /*X.520-at-organizationalUnitName (2 5 4 11) */
"\x55\x04\x0C", /*X.520-at-title (2 5 4 12) */
"\x55\x04\x0D", /*X.520-at-description (2 5 4 13) */
"\x55\x04\x0E", /*X.520-at-searchGuide (2 5 4 14) */
"\x55\x04\x0F", /*X.520-at-businessCategory (2 5 4 15) */
"\x55\x04\x10", /*X.520-at-postalAddress (2 5 4 16) */
"\x55\x04\x11", /*X.520-at-postalCode (2 5 4 17) */
"\x55\x04\x12", /*X.520-at-postOfficeBox (2 5 4 18) */
"\x55\x04\x13", /*X.520-at-physicalDeliveryOfficeName (2 5 4 19) */
"\x55\x04\x14", /*X.520-at-telephoneNumber (2 5 4 20) */
"\x55\x04\x15", /*X.520-at-telexNumber (2 5 4 21) */
"\x55\x04\x16", /*X.520-at-teletexTerminalIdentifier (2 5 4 22) */
"\x55\x04\x17", /*X.520-at-facsimileTelephoneNumber (2 5 4 23) */
"\x55\x04\x18", /*X.520-at-x121AddreX.520-at-ss (2 5 4 24) */
"\x55\x04\x19", /*X.520-at-internationalISNNumber (2 5 4 25) */
"\x55\x04\x1A", /*X.520-at-registeredAddress (2 5 4 26) */
"\x55\x04\x1B", /*X.520-at-destinationIndicator (2 5 4 27) */
"\x55\x04\x1C", /*X.520-at-preferredDeliveryMehtod (2 5 4 28) */
"\x55\x04\x1D", /*X.520-at-presentationAddress (2 5 4 29) */
"\x55\x04\x1E", /*X.520-at-supportedApplicationContext (2 5 4 30) */
"\x55\x04\x1F", /*X.520-at-member (2 5 4 31) */
"\x55\x04\x20", /*X.520-at-owner (2 5 4 32) */
"\x55\x04\x21", /*X.520-at-roleOccupant (2 5 4 33) */
"\x55\x04\x22", /*X.520-at-seeAlso (2 5 4 34) */
"\x55\x04\x23", /*X.520-at-userPassword (2 5 4 35) */
"\x55\x04\x24", /*X.520-at-userCertificate (2 5 4 36) */
"\x55\x04\x25", /*X.520-at-CAcertificate (2 5 4 37) */
"\x55\x04\x26", /*X.520-at-authorityRevocationList (2 5 4 38) */
"\x55\x04\x27", /*X.520-at-certifcateRevocationList (2 5 4 39) */
"\x55\x04\x28", /*X.520-at-crossCertificatePair (2 5 4 40) */
"\x55\x04\x34", /*X.520-at-supportedAlgorithms (2 5 4 52) */
"\x55\x04\x35", /*X.520-at-deltaRevocationList (2 5 4 53) */
"\x55\x04\x3A", /*X.520-at-crossCertificatePair (2 5 4 58) */
/* X500 algorithms */
"\x55\x08", /*X500-Algorithms (2 5 8) */
"\x55\x08\x01", /*X500-Alg-Encryption (2 5 8 1) */
"\x55\x08\x01\x01", /*rsa (2 5 8 1 1) */
/* X.509 id-ce = 2 5 29*/
"\x55\x1D\x01", /*X.509-ce-authorityKeyIdentifier (2 5 29 1) */
"\x55\x1D\x02", /*X.509-ce-keyAttributes (2 5 29 2) */
"\x55\x1D\x03", /*X.509-ce-certificatePolicies (2 5 29 3) */
"\x55\x1D\x04", /*X.509-ce-keyUsageRestriction (2 5 29 4) */
"\x55\x1D\x05", /*X.509-ce-policyMapping (2 5 29 5) */
"\x55\x1D\x06", /*X.509-ce-subtreesConstraint (2 5 29 6) */
"\x55\x1D\x07", /*X.509-ce-subjectAltName (2 5 29 7) */
"\x55\x1D\x08", /*X.509-ce-issuerAltName (2 5 29 8) */
"\x55\x1D\x09", /*X.509-ce-subjectDirectoryAttributes (2 5 29 9) */
"\x55\x1D\x0A", /*X.509-ce-basicConstraints x.509 (2 5 29 10) */
"\x55\x1D\x0B", /*X.509-ce-nameConstraints (2 5 29 11) */
"\x55\x1D\x0C", /*X.509-ce-policyConstraints (2 5 29 12) */
"\x55\x1D\x0D", /*X.509-ce-basicConstraints 9.55 (2 5 29 13) */
"\x55\x1D\x0E", /*X.509-ce-subjectKeyIdentifier (2 5 29 14) */
"\x55\x1D\x0F", /*X.509-ce-keyUsage (2 5 29 15) */
"\x55\x1D\x10", /*X.509-ce-privateKeyUsagePeriod (2 5 29 16) */
"\x55\x1D\x11", /*X.509-ce-subjectAltName (2 5 29 17) */
"\x55\x1D\x12", /*X.509-ce-issuerAltName (2 5 29 18) */
"\x55\x1D\x13", /*X.509-ce-basicConstraints (2 5 29 19) */
"\x55\x1D\x14", /*X.509-ce-cRLNumber (2 5 29 20) */
"\x55\x1D\x15", /*X.509-ce-reasonCode (2 5 29 21) */
"\x55\x1D\x17", /*X.509-ce-instructionCode (2 5 29 23) */
"\x55\x1D\x18", /*X.509-ce-invalidityDate (2 5 29 24) */
"\x55\x1D\x1B", /*X.509-ce-deltaCRLIndicator (2 5 29 27) */
"\x55\x1D\x1C", /*X.509-ce-issuingDistributionPoint (2 5 29 28) */
"\x55\x1D\x1D", /*X.509-ce-certificateIssuer (2 5 29 29) */
"\x55\x1D\x1E", /*X.509-ce-nameConstraints (2 5 29 30) */
"\x55\x1D\x1F", /*X.509-ce-cRLDistPoints (2 5 29 31) */
"\x55\x1D\x20", /*X.509-ce-certificatePolicies (2 5 29 32) */
"\x55\x1D\x21", /*X.509-ce-policyMappings (2 5 29 33) */
"\x55\x1D\x23", /*X.509-ce-authorityKeyIdentifier (2 5 29 35) */
"\x55\x1D\x24", /*X.509-ce-policyConstraints (2 5 29 36) */
/* DMS-SDN-702 */
"\x60\x86\x48\x01\x65\x02\x01\x01\x01", /*id-sdnsSignatureAlgorithm (2 16 840 1 101 2 1 1 1) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x02", /*id-mosaicSignatureAlgorithm (2 16 840 1 101 2 1 1 2) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x03", /*id-sdnsConfidentialityAlgorithm (2 16 840 1 101 2 1 1 3) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x04", /*id-mosaicConfidentialityAlgorithm (2 16 840 1 101 2 1 1 4) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x05", /*id-sdnsIntegrityAlgorithm (2 16 840 1 101 2 1 1 5) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x06", /*id-mosaicIntegrityAlgorithm (2 16 840 1 101 2 1 1 6) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x07", /*id-sdnsTokenProtectionAlgorithm (2 16 840 1 101 2 1 1 7) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x08", /*id-mosaicTokenProtectionAlgorithm (2 16 840 1 101 2 1 1 8) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x09", /*id-sdnsKeyManagementAlgorithm (2 16 840 1 101 2 1 1 9) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x0A", /*id-mosaicKeyManagementAlgorithm (2 16 840 1 101 2 1 1 10) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x0B", /*id-sdnsKMandSigAlgorithm (2 16 840 1 101 2 1 1 11) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x0C", /*id-mosaicKMandSigAlgorithm (2 16 840 1 101 2 1 1 12) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x0D", /*id-SuiteASignatureAlgorithm (2 16 840 1 101 2 1 1 13) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x0E", /*id-SuiteAConfidentialityAlgorithm (2 16 840 1 101 2 1 1 14) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x0F", /*id-SuiteAIntegrityAlgorithm (2 16 840 1 101 2 1 1 15) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x10", /*id-SuiteATokenProtectionAlgorithm (2 16 840 1 101 2 1 1 16) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x11", /*id-SuiteAKeyManagementAlgorithm (2 16 840 1 101 2 1 1 17) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x12", /*id-SuiteAKMandSigAlgorithm (2 16 840 1 101 2 1 1 18) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x13", /*id-mosaicUpdatedSigAlgorithm (2 16 840 1 101 2 1 1 19) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x14", /*id-mosaicKMandUpdSigAlgorithms (2 16 840 1 101 2 1 1 20) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x15", /*id-mosaicUpdatedIntegAlgorithm (2 16 840 1 101 2 1 1 21) */
"\x60\x86\x48\x01\x65\x02\x01\x01\x16", /*id-mosaicKeyEncryptionAlgorithm (2 16 840 1 101 2 1 1 22) */
/* Netscape */
"\x60\x86\x48\x01\x86\xF8\x42\x01\x01", /*netscape-cert-type (2 16 840 1 113730 1 1) */
"\x60\x86\x48\x01\x86\xF8\x42\x01\x02", /*netscape-base-url (2 16 840 1 113730 1 2) */
"\x60\x86\x48\x01\x86\xF8\x42\x01\x03", /*netscape-revocation-url (2 16 840 1 113730 1 3) */
"\x60\x86\x48\x01\x86\xF8\x42\x01\x04", /*netscape-ca-revocation-url (2 16 840 1 113730 1 4) */
"\x60\x86\x48\x01\x86\xF8\x42\x02\x05", /*netscape-cert-sequence (2 16 840 1 113730 2 5) */
"\x60\x86\x48\x01\x86\xF8\x42\x02\x06", /*netscape-cert-url (2 16 840 1 113730 2 6) */
"\x60\x86\x48\x01\x86\xF8\x42\x01\x07", /*netscape-renewal-url (2 16 840 1 113730 1 7) */
"\x60\x86\x48\x01\x86\xF8\x42\x01\x08", /*netscape-ca-policy-url (2 16 840 1 113730 1 8) */
"\x60\x86\x48\x01\x86\xF8\x42\x01\x09", /*netscape-HomePage-url (2 16 840 1 113730 1 9) */
"\x60\x86\x48\x01\x86\xF8\x42\x01\x0A", /*netscape-EntityLogo (2 16 840 1 113730 1 10) */
"\x60\x86\x48\x01\x86\xF8\x42\x01\x0B", /*netscape-UserPicture (2 16 840 1 113730 1 11) */
"\x60\x86\x48\x01\x86\xF8\x42\x01\x0C", /*netscape-ssl-server-name (2 16 840 1 113730 1 12) */
"\x60\x86\x48\x01\x86\xF8\x42\x01\x0D", /*netscape-comment (2 16 840 1 113730 1 13) */
"\x60\x86\x48\x01\x86\xF8\x42\x02", /*netscape-data-type (2 16 840 1 113730 2) */
"\x60\x86\x48\x01\x86\xF8\x42\x02\x01", /*netscape-dt-GIF (2 16 840 1 113730 2 1) */
"\x60\x86\x48\x01\x86\xF8\x42\x02\x02", /*netscape-dt-JPEG (2 16 840 1 113730 2 2) */
"\x60\x86\x48\x01\x86\xF8\x42\x02\x03", /*netscape-dt-URL (2 16 840 1 113730 2 3) */
"\x60\x86\x48\x01\x86\xF8\x42\x02\x04", /*netscape-dt-HTML (2 16 840 1 113730 2 4) */
"\x60\x86\x48\x01\x86\xF8\x42\x02\x05", /*netscape-dt-CertSeq (2 16 840 1 113730 2 5) */
"\x60\x86\x48\x01\x86\xF8\x42\x03", /*netscape-directory (2 16 840 1 113730 3) */
/* SET */
"\x86\x8D\x6F\x02", /*hashedRootKey (2 54 1775 2) */
"\x86\x8D\x6F\x03", /*certificateType (2 54 1775 3) */
"\x86\x8D\x6F\x04", /*merchantData (2 54 1775 4) */
"\x86\x8D\x6F\x05", /*cardCertRequired (2 54 1775 5) */
"\x86\x8D\x6F\x06", /*tunneling (2 54 1775 6) */
"\x86\x8D\x6F\x07", /*setQualifier (2 54 1775 7) */
"\x86\x8D\x6F\x63", /*set-data (2 54 1775 99) */
NULL
};
/*------------------------------------------------------------------------------
Global Variables
------------------------------------------------------------------------------*/
BYTE
*pDictMemory = NULL_PTR,
DictVersion = 0;
BYTE*
dwPtrMax = 0;
USHORT
usDictCount = 0;
#ifdef _STUDY
FILE
*pfdLog,
*pfdLogFreq,
*pfdBinAc256,
*pfdBinAc16,
*pfdBinAc4,
*pfdBinAc2;
int
sum, i,
Ac256[256],
Ac16[16],
Ac4[4],
Ac2[2];
#endif
/*------------------------------------------------------------------------------
Static Functions Declaration
------------------------------------------------------------------------------*/
static int CC_Comp(BLOC *pCertificate,
BLOC *pCompressedCertificate
);
static int CC_Uncomp(BLOC *pCompressedCertificate,
BLOC *pUncompressedCertificate
);
static int CC_ExtractContent(ASN1 *pAsn1
);
static int CC_BuildAsn1(ASN1 *pAsn1
);
static int SearchDataByIndex(USHORT usIndex,
BYTE *pDict,
BLOC *pOutBloc
);
static int CC_RawEncode(BLOC *pInBloc,
BLOC *pOutBloc,
BOOL bUseDictionnary
);
static int CC_RawDecode(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength,
BOOL bUseDictionnary
);
static int CC_GenericCompress(BLOC *pUncompBloc,
BLOC *pCompBloc,
BYTE AlgoID
);
static int CC_GenericUncompress(BLOC *pCompBloc,
BLOC *pUncompBloc,
BYTE AlgoID
);
static int CC_Encode_TBSCertificate(BLOC *pInBloc,
BLOC *pOutBloc
);
static int CC_Encode_CertificateSerialNumber(BLOC *pInBloc,
BLOC *pOutBloc
);
static int CC_Encode_AlgorithmIdentifier(BLOC *pInBloc,
BLOC *pOutBloc
);
static int CC_Encode_Name(BLOC *pInBloc,
BLOC *pOutBloc
);
static int CC_Encode_RDN(BLOC *pInBloc,
BLOC *pOutBloc
);
static int CC_Encode_AVA(BLOC *pInBloc,
BLOC *pOutBloc
);
static int CC_Encode_Validity(BLOC *pInBloc,
BLOC *pOutBloc
);
static int CC_Encode_UTCTime(BLOC *pInBloc,
BLOC *pOutBloc,
BYTE *pFormat
);
static int CC_Encode_SubjectPKInfo(BLOC *pInBloc,
BLOC *pOutBloc
);
static int CC_Encode_UniqueIdentifier(BLOC *pInBloc,
BLOC *pOutBloc
);
static int CC_Encode_Extensions(BLOC *pInBloc,
BLOC *pOutBloc
);
static int CC_Encode_Extension(BLOC *pInBloc,
BLOC *pOutBloc
);
static int CC_Encode_Signature(BLOC *pInBloc,
BLOC *pOutBloc
);
static int CC_Decode_TBSCertificate(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
);
static int CC_Decode_CertificateSerialNumber(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
);
static int CC_Decode_AlgorithmIdentifier(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
);
static int CC_Decode_Name(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
);
static int CC_Decode_RDN(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
);
static int CC_Decode_AVA(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
);
static int CC_Decode_Validity(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
);
static int CC_Decode_UTCTime(BYTE *pInData,
BYTE Format,
BLOC *pOutBloc,
USHORT *pLength
);
static int CC_Decode_SubjectPKInfo(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
);
static int CC_Decode_UniqueIdentifier(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
);
static int CC_Decode_Extensions(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
);
static int CC_Decode_Extension(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
);
static int CC_Decode_Signature(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
);
/*------------------------------------------------------------------------------
* static DWORD get_file_len(BYTE *lpszFileName)
*
* Description : Get length of file.
*
* Remarks : Nothing.
*
* In : lpszFileName = Name of file.
*
* Out : Nothing.
*
* Responses : size of file, -1 if error occur.
*
------------------------------------------------------------------------------*/
static DWORD get_file_len(BYTE *lpszFileName)
{
int fp;
DWORD nLen;
fp = _open(lpszFileName, O_RDONLY);
if (fp != 0)
{
nLen = _filelength(fp);
_close(fp);
}
else
{
nLen = -1;
}
return(nLen);
}
/*******************************************************************************
* int CC_Init(BYTE bDictMode, BYTE *pszDictName)
*
* Description : Lit le dictionnaire et son numéro de version depuis la base de
* registre vers la mémoire.
*
* Remarks :
*
* In :
*
* Out :
*
* Responses :
*
*******************************************************************************/
int CC_Init(BYTE bDictMode, BYTE *pszDictName)
{
switch (bDictMode)
{
#ifndef _STATIC
/* Dictionary read as resource data GPK_X509_DICTIONARY */
case DICT_STANDARD:
{
LPBYTE pbDict;
DWORD cbDict;
HRSRC hRsrc;
HGLOBAL hDict;
hRsrc = FindResource(g_hInstRes,
//MAKEINTRESOURCE(GPK_X509_DICTIONARY),
TEXT("GPK_X509_DICTIONARY"),
RT_RCDATA
);
if (NULL == hRsrc)
{
goto ERROR_INIT;
}
cbDict = SizeofResource(g_hInstRes, hRsrc);
if (0 == cbDict)
{
goto ERROR_INIT;
}
hDict = LoadResource(g_hInstRes, hRsrc);
if (NULL == hDict)
{
goto ERROR_INIT;
}
pbDict = LockResource(hDict);
if (NULL == pbDict)
{
goto ERROR_INIT;
}
DictVersion = *pbDict;
usDictCount = (WORD)cbDict - 1;
pDictMemory = GMEM_Alloc(usDictCount);
if (pDictMemory == NULL)
{
goto ERROR_INIT;
}
memcpy(pDictMemory, &pbDict[1], usDictCount);
return(RV_SUCCESS);
}
break;
#endif
/* Dictionary read as registyry entry in HKEY_LOCAL_MACHINE with key as */
/* pszDictName parameter */
case DICT_REGISTRY:
{
DWORD
err,
dwIgn;
HKEY
hRegKey;
BYTE
*ptr;
if (pszDictName == NULL_PTR)
{
goto ERROR_INIT;
}
err = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
(const char *) pszDictName,
0L,
"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hRegKey,
&dwIgn
);
if(err != ERROR_SUCCESS)
{
goto ERROR_INIT;
}
dwIgn = 0;
err = RegQueryValueEx(hRegKey,
"X509 Dictionary",
NULL,
NULL,
NULL,
&dwIgn
);
if(err != ERROR_SUCCESS)
{
RegCloseKey(hRegKey);
goto ERROR_INIT;
}
ptr = GMEM_Alloc(dwIgn);
if (ptr == NULL)
{
RegCloseKey(hRegKey);
goto ERROR_INIT;
}
err = RegQueryValueEx(hRegKey,
"X509 Dictionary",
NULL,
NULL,
ptr,
&dwIgn
);
if(err != ERROR_SUCCESS)
{
RegCloseKey(hRegKey);
GMEM_Free(ptr);
goto ERROR_INIT;
}
DictVersion = (BYTE)ptr[0];
usDictCount = (WORD)dwIgn - 1;
pDictMemory = GMEM_Alloc(usDictCount);
if (pDictMemory == NULL)
{
RegCloseKey(hRegKey);
GMEM_Free(ptr);
goto ERROR_INIT;
}
memcpy(pDictMemory, &ptr[1], usDictCount);
RegCloseKey(hRegKey);
GMEM_Free(ptr);
return(RV_SUCCESS);
}
break;
/* Dictionary read as file in path pszDictName parameter */
case DICT_FILE:
{
DWORD
dwFileLen;
BYTE
*ptr;
FILE
*fp;
if (pszDictName == NULL_PTR)
{
goto ERROR_INIT;
}
dwFileLen = get_file_len(pszDictName);
ptr = GMEM_Alloc(dwFileLen);
if (ptr == NULL)
{
goto ERROR_INIT;
}
fp = fopen(pszDictName, "rb");
if (fp == NULL)
{
GMEM_Free(ptr);
goto ERROR_INIT;
}
if (!fread(ptr, dwFileLen, 1, fp))
{
fclose(fp);
GMEM_Free(ptr);
goto ERROR_INIT;
}
fclose(fp);
DictVersion = (BYTE)ptr[0];
usDictCount = (WORD)dwFileLen - 1;
pDictMemory = GMEM_Alloc(usDictCount);
if (pDictMemory == NULL)
{
GMEM_Free(ptr);
goto ERROR_INIT;
}
memcpy(pDictMemory, &ptr[1], usDictCount);
GMEM_Free(ptr);
return(RV_SUCCESS);
}
break;
default:
break;
}
ERROR_INIT:
DictVersion = 0;
usDictCount = 0;
pDictMemory = NULL_PTR;
return(RV_BAD_DICTIONARY);
}
/*******************************************************************************
* int CC_Exit(void)
*
* Description : Free dictionary.
*
* Remarks :
*
* In :
*
* Out :
*
* Responses :
*
*******************************************************************************/
int CC_Exit(void)
{
DictVersion = 0;
usDictCount = 0;
if (pDictMemory != NULL_PTR)
{
GMEM_Free(pDictMemory);
}
pDictMemory = NULL_PTR;
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_Compress(BLOC *pCertificate,
* BLOC *pCompressedCertificate
* )
*
* Description : Fonction de méta-compression visible depuis l'extérieur.
* Adapte la sortie en fonction de la faisabilité d'une compression
* suivie d'une décompression.
*
* Remarks : Le champ pData du bloc d'entrée a été alloué par la fonction appelant.
* Le champ pData du bloc de sortie est alloué ici. Il doit être
* désalloué par la fonction appelant (sauf si RV_MALLOC_FAILED).
*
* In : *pCert : Bloc à méta-compresser
*
* Out : *pCompCert : Bloc 'meta-compressé'
* Si problème lors de la compression/decompression : Renvoie le bloc
* d'entrée précédé d'un tag spécifique.
* Sinon : Renvoie le bloc compressé précédé du numéro de version
* du dictionnaire.
*
* Responses : RV_SUCCESS : All is OK.
* RV_COMPRESSION_FAILED : Un problème a eu lieu lors de l'étape
* de compression/décompression donc le
* bloc de sortie contient le bloc d'entrée
* précédé du tag TAG_COMPRESSION_FAILED.
* RV_BLOC_TOO_LONG : Le bloc d'entrée *commence* par un certificat
* dont la compression a pu être inversée.
* Le bloc de sortie contient donc le compressé
* de cette partie initiale seulement.
* RV_MALLOC_FAILED : Un malloc a échoué au niveau 'méta'. C'est le
* seul réel retour d'erreur.
*
*******************************************************************************/
int CC_Compress(BLOC *pCert,
BLOC *pCompCert
)
{
BLOC
TryCompCert,
TryUncompCert;
TryCompCert.pData = NULL_PTR;
TryCompCert.usLen = 0;
TryUncompCert.pData = NULL_PTR;
TryUncompCert.usLen = 0;
#ifdef _STUDY
/* Ouverture des fichiers de log */
if ((pfdLog = fopen("CompCert.log", "a+")) == 0)
{
return(RV_FILE_OPEN_FAILED);
}
fprintf(pfdLog, "\n*****************************************************\n");
if ((pfdBinAc256 = fopen("Freq256.bin", "r+b")) == 0)
{
if ((pfdBinAc256 = fopen("Freq256.bin", "w+b")) == 0)
{
return(RV_FILE_OPEN_FAILED);
}
memset(Ac256, 0x00, 256 * sizeof(int));
}
else
{
fread(Ac256, sizeof(int), 256, pfdBinAc256);
}
if ((pfdBinAc16 = fopen("Freq016.bin", "r+b")) == 0)
{
if ((pfdBinAc16 = fopen("Freq016.bin", "w+b")) == 0)
{
return(RV_FILE_OPEN_FAILED);
}
memset(Ac16, 0x00, 16 * sizeof(int));
}
else
{
fread(Ac16, sizeof(int), 16, pfdBinAc16);
}
if ((pfdBinAc4 = fopen("Freq004.bin", "r+b")) == 0)
{
if ((pfdBinAc4 = fopen("Freq004.bin", "w+b")) == 0)
{
return(RV_FILE_OPEN_FAILED);
}
memset(Ac4, 0x00, 4 * sizeof(int));
}
else
{
fread(Ac4, sizeof(int), 4, pfdBinAc4);
}
if ((pfdBinAc2 = fopen("Freq002.bin", "r+b")) == 0)
{
if ((pfdBinAc2 = fopen("Freq002.bin", "w+b")) == 0)
{
return(RV_FILE_OPEN_FAILED);
}
memset(Ac2, 0x00, 2 * sizeof(int));
}
else
{
fread(Ac2, sizeof(int), 2, pfdBinAc2);
}
#endif
if (CC_Comp(pCert, &TryCompCert) != RV_SUCCESS)
{
/* Si la compression s'est mal passée alors on renvoie le fichier
d'entrée en indiquant que le fichier n'est pas compressé */
if (TryCompCert.pData)
{
GMEM_Free(TryCompCert.pData);
TryCompCert.pData = NULL_PTR;
}
/* Allocation de la mémoire pour le certificat compressé */
if (pCompCert->usLen < pCert->usLen + 1)
{
pCompCert->usLen = pCert->usLen + 1;
if (pCompCert->pData)
{
return(RV_BUFFER_TOO_SMALL);
}
else
{
return(RV_SUCCESS);
}
}
pCompCert->usLen = pCert->usLen + 1;
pCompCert->pData[0] = TAG_COMPRESSION_FAILED;
if (pCompCert->pData)
{
memcpy(&pCompCert->pData[1], pCert->pData, pCert->usLen);
}
return(RV_COMPRESSION_FAILED);
}
if ( ( (CC_Uncomp(&TryCompCert, &TryUncompCert) != RV_SUCCESS)
|| (pCert->usLen != TryUncompCert.usLen)
|| (memcmp(TryUncompCert.pData, pCert->pData, pCert->usLen) != 0)
)
&& (memcmp(TryUncompCert.pData, pCert->pData, TryUncompCert.usLen) != 0)
)
{
/* Si la décompression s'est mal passée ou bien si elle n'est pas fidèle
alors on renvoie le fichier d'entrée en indiquant que le fichier
n'est pas compressé */
if (TryCompCert.pData)
{
GMEM_Free(TryCompCert.pData);
TryCompCert.pData = NULL_PTR;
}
if (TryUncompCert.pData)
{
GMEM_Free(TryUncompCert.pData);
TryUncompCert.pData = NULL_PTR;
}
/* Allocation de la mémoire pour le certificat */
if (pCompCert->usLen < pCert->usLen + 1)
{
pCompCert->usLen = pCert->usLen + 1;
if (pCompCert->pData)
{
return(RV_BUFFER_TOO_SMALL);
}
else
{
return(RV_SUCCESS);
}
}
pCompCert->usLen = pCert->usLen + 1;
pCompCert->pData[0] = TAG_COMPRESSION_FAILED;
if (pCompCert->pData)
{
memcpy(&pCompCert->pData[1], pCert->pData, pCert->usLen);
}
return(RV_COMPRESSION_FAILED);
}
#ifdef _STUDY
fseek(pfdBinAc256, 0, SEEK_SET);
fwrite(Ac256, sizeof(int), 256, pfdBinAc256);
fseek(pfdBinAc16, 0, SEEK_SET);
fwrite(Ac16, sizeof(int), 16, pfdBinAc16);
fseek(pfdBinAc4, 0, SEEK_SET);
fwrite(Ac4, sizeof(int), 4, pfdBinAc4);
fseek(pfdBinAc2, 0, SEEK_SET);
fwrite(Ac2, sizeof(int), 2, pfdBinAc2);
if ((pfdLogFreq = fopen("Freq.log", "w")) == 0)
{
return(RV_FILE_OPEN_FAILED);
}
for (sum = 0, i = 0; i < 256; sum += Ac256[i], i++) ;
fprintf(pfdLogFreq, "\nTotal = %d\n\n", sum * 8);
for (i = 0; i < 2; i++)
{
fprintf(pfdLogFreq, "0x%02X (%03d) '%c' : %8d - %04.2f %%\n",
i, i, (isgraph(i) ? i : ' '),
Ac2[i], ((float) 100 * Ac2[i] / (sum * 8)));
}
fprintf(pfdLogFreq, "\nTotal = %d\n\n", sum * 4);
for (i = 0; i < 4; i++)
{
fprintf(pfdLogFreq, "0x%02X (%03d) '%c' : %8d - %04.2f %%\n",
i, i, (isgraph(i) ? i : ' '),
Ac4[i], ((float) 100 * Ac4[i] / (sum * 4)));
}
fprintf(pfdLogFreq, "\nTotal = %d\n\n", sum * 2);
for (i = 0; i < 16; i++)
{
fprintf(pfdLogFreq, "0x%02X (%03d) '%c' : %8d - %04.2f %%\n",
i, i, (isgraph(i) ? i : ' '),
Ac16[i], ((float) 100 * Ac16[i] / (sum * 2)));
}
fprintf(pfdLogFreq, "\nTotal = %d\n\n", sum);
for (i = 0; i < 256; i++)
{
fprintf(pfdLogFreq, "0x%02X (%03d) '%c' : %8d - %04.2f %%\n",
i, i, (isgraph(i) ? i : ' '),
Ac256[i], ((float) 100 * Ac256[i] / sum));
}
fclose(pfdBinAc256);
fclose(pfdBinAc16);
fclose(pfdBinAc4);
fclose(pfdBinAc2);
fclose(pfdLogFreq);
fclose(pfdLog);
#endif
/* Si tout s'est bien passé, on renvoie le résultat en indiquant
qu'il est compressé (DictVersion != 0xFF) */
/* Allocation de la mémoire pour le certificat */
if (pCompCert->usLen < TryCompCert.usLen + 1)
{
if (TryCompCert.pData)
{
GMEM_Free(TryCompCert.pData);
TryCompCert.pData = NULL_PTR;
}
if (TryUncompCert.pData)
{
GMEM_Free(TryUncompCert.pData);
TryUncompCert.pData = NULL_PTR;
}
pCompCert->usLen = TryCompCert.usLen + 1;
if (pCompCert->pData)
{
return(RV_BUFFER_TOO_SMALL);
}
else
{
return(RV_SUCCESS);
}
}
pCompCert->usLen = TryCompCert.usLen + 1;
if (pCompCert->pData)
{
pCompCert->pData[0] = DictVersion;
memcpy(&pCompCert->pData[1], TryCompCert.pData, TryCompCert.usLen);
}
if (TryCompCert.pData)
{
GMEM_Free(TryCompCert.pData);
TryCompCert.pData = NULL_PTR;
}
if (TryUncompCert.pData)
{
GMEM_Free(TryUncompCert.pData);
TryUncompCert.pData = NULL_PTR;
}
if (pCert->usLen != TryUncompCert.usLen)
{
return(RV_BLOC_TOO_LONG);
}
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_Uncompress(BLOC *pCompCert,
* BLOC *pUncompCert
* )
*
* Description : Fonction de méta-décompression visible depuis l'extérieur.
* Retourne le bloc original (entrée de la fonction CC_Compress)
* sous réserve toutefois d'une version adéquate du dictionnaire.
*
* Remarks : Le champ pData du bloc d'entrée a été alloué par la fonction appelant.
* Le champ pData du bloc de sortie est alloué ici. Il doit être
* désalloué par la fonction appelant (sauf si erreur).
* Le comportement est imprévisible dans le cas où le bloc d'entrée
* n'est pas le bloc de sortie d'un appel à la fonction CC_Compress.
*
* In : *pCompCert : Bloc à méta-décompresser
*
* Out : *pUncompCert : Bloc 'méta-décompressé'
* (ou vide si RV_BAD_DICTIONARY)
*
* Responses : RV_SUCCESS : All is OK.
* RV_BAD_DICTIONARY : La version du dictionnaire utilisée pour la
* décompression est plus ancienne que celle
* utilisée pour la compression.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés lors de
* la décompression.
*
*******************************************************************************/
int CC_Uncompress(BLOC *pCompCert,
BLOC *pUncompCert
)
{
int
resp;
BLOC
TempCompCert,
TempUncompCert;
if (pCompCert->pData[0] == TAG_COMPRESSION_FAILED)
{
/* Allocation de la mémoire pour le certificat
On pourrait se contenter de ne retourner que la zone mémoire
à partir de l'octet 1 mais la fonction de décompression est sensée
toujours allouer la zone dans laquelle elle renvoie le décompressé */
if(pUncompCert->usLen < pCompCert->usLen - 1)
{
pUncompCert->usLen = pCompCert->usLen - 1;
if (pUncompCert->pData)
{
return(RV_BUFFER_TOO_SMALL);
}
else
{
return(RV_SUCCESS);
}
}
pUncompCert->usLen = pCompCert->usLen - 1;
if (pUncompCert->pData)
{
memcpy(pUncompCert->pData, &pCompCert->pData[1], pUncompCert->usLen);
}
return (RV_SUCCESS);
}
else if (pCompCert->pData[0] <= DictVersion)
{
TempCompCert.pData = &pCompCert->pData[1];
TempCompCert.usLen = pCompCert->usLen - 1;
TempUncompCert.usLen = 0;
resp = CC_Uncomp(&TempCompCert, &TempUncompCert);
if (resp == RV_SUCCESS)
{
if(pUncompCert->usLen < TempUncompCert.usLen)
{
GMEM_Free(TempUncompCert.pData);
pUncompCert->usLen = TempUncompCert.usLen;
if (pUncompCert->pData)
{
return(RV_BUFFER_TOO_SMALL);
}
else
{
return(RV_SUCCESS);
}
}
pUncompCert->usLen = TempUncompCert.usLen;
if (pUncompCert->pData)
{
memcpy(pUncompCert->pData, TempUncompCert.pData, TempUncompCert.usLen);
}
GMEM_Free(TempUncompCert.pData);
}
return (resp);
}
else
{
return (RV_BAD_DICTIONARY);
}
}
/*******************************************************************************
* int CC_Comp(BLOC *pCertificate,
* BLOC *pCompressedCertificate
* )
*
* Description : Fonction interne de compression d'un certificat.
*
* Remarks : Le champ pData du bloc d'entrée a été alloué par la fonction appelant.
* Le champ pData du bloc de sortie est alloué ici. Il doit être
* désalloué par la fonction appelant (sauf si erreur).
*
* In : *pCertificate : Bloc à compresser
*
* Out : *pCompressedCertificate : Bloc compressé
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Comp(BLOC *pCertificate,
BLOC *pCompressedCertificate
)
{
ASN1
Cert,
tbsCert,
signatureAlgo,
signature;
BLOC
TmpCompCert,
tbsCertEncoded,
signatureAlgoEncoded,
signatureEncoded;
BYTE
*pCurrent;
int
rv;
/* Eclatement du certificat en ses trois composants principaux */
dwPtrMax = pCertificate->pData + pCertificate->usLen;
Cert.Asn1.pData = pCertificate->pData;
rv = CC_ExtractContent(&Cert);
if (rv != RV_SUCCESS) return rv;
if (Cert.Asn1.usLen != pCertificate->usLen)
{
return(RV_INVALID_DATA);
}
tbsCert.Asn1.pData = Cert.Content.pData;
rv = CC_ExtractContent(&tbsCert);
if (rv != RV_SUCCESS) return rv;
signatureAlgo.Asn1.pData = tbsCert.Content.pData + tbsCert.Content.usLen;
rv = CC_ExtractContent(&signatureAlgo);
if (rv != RV_SUCCESS) return rv;
signature.Asn1.pData = signatureAlgo.Content.pData + signatureAlgo.Content.usLen;
rv = CC_ExtractContent(&signature);
if (rv != RV_SUCCESS) return rv;
ASSERT(signature.Content.pData + signature.Content.usLen ==
Cert.Content.pData + Cert.Content.usLen);
/* Elaboration des composants principaux compressés */
/* Les pData des blocs *Encoded sont alloués par les fonctions CC_Encode_*.
Ils sont libérés dans cette fonction aprés usage */
tbsCertEncoded.pData = NULL;
signatureAlgoEncoded.pData = NULL;
signatureEncoded.pData = NULL;
rv = CC_Encode_TBSCertificate(&tbsCert.Content, &tbsCertEncoded);
if (rv != RV_SUCCESS) goto err;
rv = CC_Encode_AlgorithmIdentifier(&signatureAlgo.Content, &signatureAlgoEncoded);
if (rv != RV_SUCCESS) goto err;
rv = CC_Encode_Signature(&signature.Content, &signatureEncoded);
if (rv != RV_SUCCESS) goto err;
/* Reconstruction du certificat compressé à partir de ses composants */
TmpCompCert.usLen = tbsCertEncoded.usLen
+ signatureAlgoEncoded.usLen
+ signatureEncoded.usLen;
/* A désallouer par le programme appelant */
if ((TmpCompCert.pData = GMEM_Alloc(TmpCompCert.usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
pCurrent = TmpCompCert.pData;
memcpy(pCurrent, tbsCertEncoded.pData, tbsCertEncoded.usLen);
GMEM_Free(tbsCertEncoded.pData);
pCurrent += tbsCertEncoded.usLen;
memcpy(pCurrent, signatureAlgoEncoded.pData, signatureAlgoEncoded.usLen);
GMEM_Free(signatureAlgoEncoded.pData);
pCurrent += signatureAlgoEncoded.usLen;
memcpy(pCurrent, signatureEncoded.pData, signatureEncoded.usLen);
GMEM_Free(signatureEncoded.pData);
pCurrent += signatureEncoded.usLen;
/* Et maintenant on compresse le certificat compressé !! */
#ifdef _GLOBAL_COMPRESSION
rv = CC_RawEncode(&TmpCompCert, pCompressedCertificate, FALSE);
GMEM_Free(TmpCompCert.pData);
if (rv != RV_SUCCESS) goto err;
#else
*pCompressedCertificate = TmpCompCert;
#endif
return(RV_SUCCESS);
err:
GMEM_Free(tbsCertEncoded.pData);
GMEM_Free(signatureAlgoEncoded.pData);
GMEM_Free(signatureEncoded.pData);
return (rv);
}
/*******************************************************************************
* int CC_Uncomp(BLOC *pCompressedCertificate,
* BLOC *pUncompressedCertificate
* )
*
* Description : Fonction interne de décompression d'un certificat.
*
* Remarks : Le champ pData du bloc d'entrée a été alloué par la fonction appelant.
* Le champ pData du bloc de sortie est alloué ici. Il doit être
* désalloué par la fonction appelant (sauf si erreur).
*
* In : *pCertificate : Bloc à compresser
*
* Out : *pCompressedCertificate : Bloc compressé
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Uncomp(BLOC *pCompressedCertificate,
BLOC *pUncompressedCertificate
)
{
ASN1
Cert,
tbsCert,
signatureAlgo,
signature;
BLOC
TmpCompCert;
BYTE
*pCurrent;
int
rv;
USHORT
Length;
tbsCert.Asn1.pData = NULL;
signatureAlgo.Asn1.pData = NULL;
signature.Asn1.pData = NULL;
#ifdef _GLOBAL_COMPRESSION
/* Length est ici inutile */
rv = CC_RawDecode(pCompressedCertificate->pData, &TmpCompCert, &Length, FALSE);
if (rv != RV_SUCCESS) return rv;
#else
TmpCompCert = *pCompressedCertificate;
#endif
/* Décodage des différents composants du certificat */
/* CC_Decode_* et cc_BuildAsn1 allouent les pData de leurs arguments de
sortie. Ces zones sont à désallouer à ce niveau après usage. */
pCurrent = TmpCompCert.pData;
rv = CC_Decode_TBSCertificate(pCurrent, &tbsCert.Content, &Length);
if (rv != RV_SUCCESS) goto err;
tbsCert.Tag = TAG_SEQUENCE;
rv = CC_BuildAsn1(&tbsCert);
GMEM_Free(tbsCert.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
rv = CC_Decode_AlgorithmIdentifier(pCurrent, &signatureAlgo.Content, &Length);
if (rv != RV_SUCCESS) goto err;
signatureAlgo.Tag = TAG_SEQUENCE;
rv = CC_BuildAsn1(&signatureAlgo);
GMEM_Free(signatureAlgo.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
rv = CC_Decode_Signature(pCurrent, &signature.Content, &Length);
if (rv != RV_SUCCESS) goto err;
signature.Tag = TAG_BIT_STRING;
rv = CC_BuildAsn1(&signature);
GMEM_Free(signature.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
ASSERT(pCurrent == TmpCompCert.pData + TmpCompCert.usLen);
#ifdef _GLOBAL_COMPRESSION
GMEM_Free(TmpCompCert.pData);
#endif
/* Reconstruction de l'enveloppe Asn1 du certificat */
/* A désallouer à ce niveau après usage */
Cert.Content.usLen = tbsCert.Asn1.usLen
+ signatureAlgo.Asn1.usLen
+ signature.Asn1.usLen;
if ((Cert.Content.pData = GMEM_Alloc(Cert.Content.usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
pCurrent = Cert.Content.pData;
memcpy(pCurrent, tbsCert.Asn1.pData, tbsCert.Asn1.usLen);
GMEM_Free(tbsCert.Asn1.pData);
pCurrent += tbsCert.Asn1.usLen;
memcpy(pCurrent, signatureAlgo.Asn1.pData, signatureAlgo.Asn1.usLen);
GMEM_Free(signatureAlgo.Asn1.pData);
pCurrent += signatureAlgo.Asn1.usLen;
memcpy(pCurrent, signature.Asn1.pData, signature.Asn1.usLen);
GMEM_Free(signature.Asn1.pData);
pCurrent += signature.Asn1.usLen;
Cert.Tag = TAG_SEQUENCE;
rv = CC_BuildAsn1(&Cert);
GMEM_Free(Cert.Content.pData);
if (rv != RV_SUCCESS) return rv;
*pUncompressedCertificate = Cert.Asn1;
return(RV_SUCCESS);
err:
GMEM_Free(tbsCert.Asn1.pData);
GMEM_Free(signatureAlgo.Asn1.pData);
GMEM_Free(signature.Asn1.pData);
return(rv);
}
/*******************************************************************************
* int CC_ExtractContent(ASN1 *pAsn1)
*
* Description : Extrait d'un bloc Asn1 (pAsn1->Asn1) son contenu en élaguant son
* enrobage (identifier bytes, length bytes) et le place dans le
* bloc pAsn1->Content.
*
* Remarks : Le champ Asn1.pData a été alloué par la fonction appelant.
*
* In : pAsn1->Asn1.pData
*
* Out : Les champs suivants sont renseignés (si RV_SUCCESS) :
* - Tag
* - Asn1.usLen
* - Content.usLen
* - Content.pData (pas d'allocation : on fait pointer sur la partie
* adéquate du contenu de Asn1.pData)
*
* Responses : RV_SUCCESS : All is OK.
* RV_INVALID_DATA : Le format du bloc Asn1 n'est pas supporté.
*
*******************************************************************************/
int CC_ExtractContent(ASN1 *pAsn1)
{
BYTE
*pData;
int
NbBytes,
i;
pData = pAsn1->Asn1.pData;
if ((pData[0] & 0x1F) == 0x1F)
{
/* High-tag-number : non supporté */
return(RV_INVALID_DATA);
}
else
{
pAsn1->Tag = pData[0];
}
if (pData[1] == 0x80)
{
/* Constructed, indefinite-length method : non supporté */
return(RV_INVALID_DATA);
}
else if (pData[1] > 0x82)
{
/* Constructed, definite-length method : longueur trop grande */
return(RV_INVALID_DATA);
}
else if (pData[1] < 0x80)
{
/* Primitive, definite-length method */
pAsn1->Content.usLen = pData[1];
pAsn1->Content.pData = &pData[2];
pAsn1->Asn1.usLen = pAsn1->Content.usLen + 2;
/* Looking for memory violation */
if (pData + pAsn1->Content.usLen + 2 > dwPtrMax)
{
return(RV_INVALID_DATA);
}
}
else
{
/* Constructed, definite-length method */
NbBytes = pData[1] & 0x7F;
ASSERT(NbBytes <= 2);
pAsn1->Content.usLen = 0;
for (i = 0; i < NbBytes; i++)
{
pAsn1->Content.usLen = (pAsn1->Content.usLen << 8) + pData[2+i];
}
/* Looking for memory violation */
if (pData + pAsn1->Content.usLen+2+NbBytes > dwPtrMax)
{
return(RV_INVALID_DATA);
}
pAsn1->Content.pData = &pData[2+NbBytes];
pAsn1->Asn1.usLen = pAsn1->Content.usLen + 2 + NbBytes;
}
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_BuildAsn1(ASN1 *pAsn1)
*
* Description : Reconstruit un bloc Asn1 (pAsn1->Asn1) à partir de son contenu
* (pAsn1->Content) et de son Tag supposé spécifié (pAsn1->Tag)
* en synthétisant son enrobage (identifier bytes, length bytes).
*
* Remarks : Le champ Content.pData a été alloué par la fonction appelant.
* Seulement la forme 'low-tag-number' (tag sur un seul octet) est
* supportée.
*
* In : pAsn1->Content.usLen
* pAsn1->Content.pData
* pAsn1->Tag
*
* Out : Les champs suivants sont renseignés (si RV_SUCCESS) :
* - Asn1.usLen
* - Asn1.pData (alloué ici, à libérer par la fonction appelant)
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
*
*******************************************************************************/
int CC_BuildAsn1(ASN1 *pAsn1)
{
if (pAsn1->Content.usLen < 0x0080)
{
pAsn1->Asn1.usLen = pAsn1->Content.usLen + 2;
if ((pAsn1->Asn1.pData = GMEM_Alloc(pAsn1->Asn1.usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
pAsn1->Asn1.pData[0] = (BYTE) pAsn1->Tag;
pAsn1->Asn1.pData[1] = (BYTE) pAsn1->Content.usLen;
memcpy(&(pAsn1->Asn1.pData[2]), pAsn1->Content.pData, pAsn1->Content.usLen);
}
else
{
if (pAsn1->Content.usLen < 0x0100)
{
pAsn1->Asn1.usLen = pAsn1->Content.usLen + 3;
if ((pAsn1->Asn1.pData = GMEM_Alloc(pAsn1->Asn1.usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
pAsn1->Asn1.pData[0] = pAsn1->Tag;
pAsn1->Asn1.pData[1] = 0x81;
pAsn1->Asn1.pData[2] = (BYTE)pAsn1->Content.usLen;
memcpy(&(pAsn1->Asn1.pData[3]), pAsn1->Content.pData, pAsn1->Content.usLen);
}
else
{
pAsn1->Asn1.usLen = pAsn1->Content.usLen + 4;
if ((pAsn1->Asn1.pData = GMEM_Alloc(pAsn1->Asn1.usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
pAsn1->Asn1.pData[0] = pAsn1->Tag;
pAsn1->Asn1.pData[1] = 0x82;
pAsn1->Asn1.pData[2] = pAsn1->Content.usLen >> 8;
pAsn1->Asn1.pData[3] = pAsn1->Content.usLen & 0x00FF;
memcpy(&(pAsn1->Asn1.pData[4]), pAsn1->Content.pData, pAsn1->Content.usLen);
}
}
return(RV_SUCCESS);
}
/*******************************************************************************
* int SearchDataByIndex(USHORT usIndex,
* BYTE *pDict,
* BLOC *pOutBloc
* )
*
* Description : Recherche l'entrée (mot/phrase) dans le dictionnaire dont
* l'index est spécifié en entrée.
*
* Remarks : Le format du dictionnaire est le suivant :
*
* - 2 octets : le nombre d'entrées
* - 2 octets : la longueur totale du dictionnaire
*
* - 2 octets : I0, l'index de l'entrée 0
* - 2 octets : L0, la longueur de l'entrée 0
* - L0 octets : l'entrée 0
*
* - 2 octets : I1, l'index de l'entrée 1
* - 2 octets : L1, la longueur de l'entrée 1
* - L1 octets : l'entrée 1
*
* - ........
*
* In : usIndex : l'index du mot/phrase recherché
* pDict : pointe sur le dictionnaire chargé en mémoire
*
* Out : pOutBloc : l'entrée correspondant à l'index
*
* Responses : RV_SUCCESS : All is OK.
* RV_BAD_DICTIONARY : Aucune entrée ayant le bon index n'a été
* trouvée dans le dictionnaire.
*
*******************************************************************************/
int SearchDataByIndex(USHORT usIndex,
BYTE *pDict,
BLOC *pOutBloc
)
{
BYTE
*pCurrent;
BOOL
bFound = FALSE;
USHORT
i,
usLength,
usCount,
usCurrent;
usCount = *(USHORT *)pDict; //memcpy(&usCount, pDict, sizeof(usCount));
pCurrent = pDict + 4;
bFound = FALSE;
for (i = 0; i < usCount; i++)
{
usCurrent = *(USHORT UNALIGNED *)pCurrent; //memcpy(&usCurrent, (USHORT *) pCurrent, 2);
pCurrent += 2;
if (usCurrent == usIndex)
{
bFound = TRUE;
break;
}
usLength = *(USHORT UNALIGNED *)pCurrent; //memcpy(&usLength, (USHORT *) pCurrent, 2);
pCurrent += (2 + usLength);
}
if (!bFound)
{
return(RV_BAD_DICTIONARY);
}
usLength = *(USHORT UNALIGNED *)pCurrent; //memcpy(&usLength, (USHORT *) pCurrent, 2);
pCurrent += 2;
pOutBloc->pData = pCurrent;
pOutBloc->usLen = usLength;
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_RawEncode(BLOC *pInBloc,
* BLOC *pOutBloc,
* BOOL bUseDictionary
* )
*
* Description : Traite le bloc d'entrée comme une donnée terminale dans le
* processus d'extractions successives des enrobages Asn1.
* Le but est ici de compresser au maximum ce bloc sans faire
* aucune hypothèse sur sa structure Asn1. Pour ce faire, on
* commence (si bUseDictionary == TRUE) par remplacer chaque
* mot/phrase du dictionnaire rencontré par son index précédé d'un
* caractère d'échappement, puis on applique à la donnée résiduelle
* successivement chaque algorithme de compression statistique pour
* n'en retenir que le meilleur. La sortie est le meilleur
* compressé du résidu précédé d'un header codant le numéro de
* l'algo ainsi que la longueur du compressé.
*
* Remarks :
*
* In : pInBloc : le bloc à encoder
* bUseDictionary : on peut ne pas utiliser le dictionnaire
*
* Out : pOutBloc : le bloc encodé (mémoire allouée ici à libérer par le
* programme appelant)
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* RV_INVALID_DATA : Le meilleur compressé du résidu est trop long.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_RawEncode(BLOC *pInBloc,
BLOC *pOutBloc,
BOOL bUseDictionary
)
{
BLOC
OldBloc,
NewBloc,
CompBloc,
BestBloc;
BOOL
bFound;
BYTE
*pCurrent,
*pToCurrent,
*pFromCurrent,
*pData,
BestAlgoId;
int
// value,
rv;
USHORT
pos,
usEscapeCount,
usIndex,
usLength,
usCount,
usCurrent;
/* Il peut être intéressant de ne pas utiliser le dictionnaire si on sait
qu'il ne va pas servir car cela evite de doubler les 0xFF pour rien */
if (bUseDictionary == FALSE)
{
OldBloc.usLen = pInBloc->usLen;
if ((OldBloc.pData = GMEM_Alloc(OldBloc.usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
memcpy(OldBloc.pData, pInBloc->pData, OldBloc.usLen);
}
else
{
/* On recopie le bloc d'entrée dans un bloc de travail en doublant les 'escape' */
pCurrent = pInBloc->pData;
usEscapeCount = 0;
for (pos = 0; pos < pInBloc->usLen; pos++)
{
if (*pCurrent == ESCAPE_CHAR)
{
usEscapeCount++;
}
pCurrent++;
}
OldBloc.usLen = pInBloc->usLen + usEscapeCount;
if ((OldBloc.pData = GMEM_Alloc(OldBloc.usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
pFromCurrent = pInBloc->pData;
pToCurrent = OldBloc.pData;
for (pos = 0; pos < pInBloc->usLen; pos++)
{
if ((*pToCurrent = *pFromCurrent) == ESCAPE_CHAR)
{
pToCurrent++;
*pToCurrent = ESCAPE_CHAR;
}
pFromCurrent++;
pToCurrent++;
}
/* Si un dictionnaire existe, on l'utilise pour coder ses entrées rencontrées */
if (pDictMemory != NULL_PTR)
{
pCurrent = pDictMemory;
memcpy(&usCount, pCurrent, sizeof(usCount));
pCurrent += 4;
for (usCurrent = 0; usCurrent < usCount; usCurrent++)
{
memcpy(&usIndex, pCurrent, sizeof(usIndex));
pCurrent += 2;
memcpy(&usLength, pCurrent, sizeof(usLength));
pCurrent += 2;
if (usLength <= OldBloc.usLen)
{
bFound = FALSE;
for (pos = 0; pos < OldBloc.usLen - usLength + 1; pos++)
{
if (memcmp(pCurrent, OldBloc.pData + pos, usLength) == 0)
{
bFound = TRUE;
break;
}
}
if (bFound)
{
if (usIndex < 0x80)
{
NewBloc.usLen = OldBloc.usLen - usLength + 2;
if ((NewBloc.pData = GMEM_Alloc(NewBloc.usLen)) == NULL_PTR)
{
GMEM_Free(OldBloc.pData);
return(RV_MALLOC_FAILED);
}
memcpy(NewBloc.pData, OldBloc.pData, pos);
NewBloc.pData[pos] = ESCAPE_CHAR;
NewBloc.pData[pos + 1] = (BYTE) usIndex;
memcpy(NewBloc.pData + pos + 2,
OldBloc.pData + pos + usLength,
OldBloc.usLen - pos - usLength);
GMEM_Free(OldBloc.pData);
}
else
{
NewBloc.usLen = OldBloc.usLen - usLength + 3;
if ((NewBloc.pData = GMEM_Alloc(NewBloc.usLen)) == NULL_PTR)
{
GMEM_Free(OldBloc.pData);
return(RV_MALLOC_FAILED);
}
memcpy(NewBloc.pData, OldBloc.pData, pos);
NewBloc.pData[pos] = ESCAPE_CHAR;
NewBloc.pData[pos + 1] = (BYTE) (usIndex >> 8) | 0x80;
NewBloc.pData[pos + 2] = (BYTE) (usIndex & 0x00FF);
memcpy(NewBloc.pData + pos + 3,
OldBloc.pData + pos + usLength,
OldBloc.usLen - pos - usLength);
GMEM_Free(OldBloc.pData);
}
OldBloc = NewBloc;
}
}
pCurrent += usLength;
}
}
}
#ifdef _STUDY
for (i = 0; i < OldBloc.usLen; i++)
{
value = OldBloc.pData[i];
Ac256[value]++;
Ac16[value & 0x0F]++;
Ac16[(value & 0xF0) >> 4]++;
Ac4[value & 0x03]++;
Ac4[(value & 0x0C) >> 2]++;
Ac4[(value & 0x30) >> 4]++;
Ac4[(value & 0xC0) >> 6]++;
Ac2[value & 0x01]++; value >>= 1;
Ac2[value & 0x01]++; value >>= 1;
Ac2[value & 0x01]++; value >>= 1;
Ac2[value & 0x01]++; value >>= 1;
Ac2[value & 0x01]++; value >>= 1;
Ac2[value & 0x01]++; value >>= 1;
Ac2[value & 0x01]++; value >>= 1;
Ac2[value & 0x01]++; value >>= 1;
}
fprintf(pfdLog, "\n");
for (i = 0; i < (OldBloc.usLen <= 8 ? OldBloc.usLen : 8); i++)
{
fprintf(pfdLog, "%02X", OldBloc.pData[i]);
}
fprintf(pfdLog, " (");
for (i = 0; i < (OldBloc.usLen <= 8 ? OldBloc.usLen : 8); i++)
{
fprintf(pfdLog, "%c", OldBloc.pData[i]);
}
fprintf(pfdLog, ")\n");
#endif
BestBloc = OldBloc;
BestAlgoId = ALGO_NONE;
#ifdef _ALGO_1
rv = CC_GenericCompress(&OldBloc, &CompBloc, ALGO_ACFX8);
if (rv == RV_MALLOC_FAILED) return rv;
// The compression algorithm may return RV_COMPRESSION_FAILED when
// the compression algorithm wants to use MORE space than the input data.
// In such a case, the algorithm returns the raw data in the compressed block
if (CompBloc.usLen < BestBloc.usLen)
{
/* On préserve OldBloc.pData qui sert pour les autres algos */
if (BestBloc.pData != OldBloc.pData)
{
GMEM_Free(BestBloc.pData);
}
BestBloc = CompBloc;
BestAlgoId = ALGO_ACFX8;
}
else
{
GMEM_Free(CompBloc.pData);
}
#endif
#ifdef _ALGO_2
rv = CC_GenericCompress(&OldBloc, &CompBloc, ALGO_ACAD8);
if (rv == RV_MALLOC_FAILED) return rv;
// The compression algorithm may return RV_COMPRESSION_FAILED when
// the compression algorithm wants to use MORE space than the input data.
// In such a case, the algorithm returns the raw data in the compressed block
if (CompBloc.usLen < BestBloc.usLen)
{
/* On préserve OldBloc.pData qui sert pour les autres algos */
if (BestBloc.pData != OldBloc.pData)
{
GMEM_Free(BestBloc.pData);
}
BestBloc = CompBloc;
BestAlgoId = ALGO_ACAD8;
}
else
{
GMEM_Free(CompBloc.pData);
}
#endif
if (BestBloc.usLen < 0x1F) /* La valeur 0x1F peut engendrer 0xFF = ESCAPE_CHAR */
{
if ((pData = GMEM_Alloc(BestBloc.usLen + 1)) == NULL_PTR)
{
GMEM_Free(BestBloc.pData);
return(RV_MALLOC_FAILED);
}
else
{
pData[0] = (BestAlgoId << 5) | BestBloc.usLen;
memcpy(&pData[1], BestBloc.pData, BestBloc.usLen);
pOutBloc->usLen = BestBloc.usLen + 1;
pOutBloc->pData = pData;
GMEM_Free(BestBloc.pData);
}
}
else if (BestBloc.usLen < 0x2000)
{
if ((pData = GMEM_Alloc(BestBloc.usLen + 3)) == NULL_PTR)
{
GMEM_Free(BestBloc.pData);
return(RV_MALLOC_FAILED);
}
else
{
pData[0] = ESCAPE_CHAR;
pData[1] = (BestAlgoId << 5) | (BestBloc.usLen >> 8);
pData[2] = BestBloc.usLen & 0xFF;
memcpy(&pData[3], BestBloc.pData, BestBloc.usLen);
pOutBloc->usLen = BestBloc.usLen + 3;
pOutBloc->pData = pData;
GMEM_Free(BestBloc.pData);
}
}
else
{
GMEM_Free(BestBloc.pData);
return(RV_INVALID_DATA);
}
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_RawDecode(BYTE *pInBloc,
* BLOC *pOutBloc,
* USHORT *pLength,
* BOOL bUseDictionnary
* )
*
* Description : Transformation inverse de 'CC_RawEncode'.
*
* Remarks :
*
* In : pInBloc : le bloc à décoder
* bUseDictionary : on peut ne pas utiliser le dictionnaire (doit
* être consistent avec l'encodage)
*
* Out : pOutBloc : le bloc décodé (mémoire allouée ici à libérer par le
* programme appelant)
* pLength : la longueur de données encodés utilisée
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_RawDecode(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength,
BOOL bUseDictionary
)
{
BLOC
OldBloc,
NewBloc,
RecordBloc,
CompData;
BYTE
AlgoId;
int
rv;
USHORT
pos,
usIndex;
if (pInData[0] == ESCAPE_CHAR)
{
AlgoId = pInData[1] >> 5;
CompData.usLen = ((pInData[1] & 0x1F) << 8) + pInData[2];
CompData.pData = &(pInData[3]);
*pLength = CompData.usLen + 3;
}
else
{
AlgoId = pInData[0] >> 5;
CompData.usLen = pInData[0] & 0x1F;
CompData.pData = &(pInData[1]);
*pLength = CompData.usLen + 1;
}
rv = CC_GenericUncompress(&CompData, &OldBloc, AlgoId);
if (rv != RV_SUCCESS) return rv;
if (bUseDictionary)
{
pos = 0;
while (pos < OldBloc.usLen)
{
if (OldBloc.pData[pos] == ESCAPE_CHAR)
{
if (OldBloc.pData[pos + 1] == ESCAPE_CHAR)
{
NewBloc.usLen = OldBloc.usLen - 1;
if ((NewBloc.pData = GMEM_Alloc(NewBloc.usLen)) == NULL_PTR)
{
GMEM_Free(OldBloc.pData);
return(RV_MALLOC_FAILED);
}
memcpy(NewBloc.pData, OldBloc.pData, pos);
NewBloc.pData[pos] = ESCAPE_CHAR;
memcpy(NewBloc.pData + pos + 1,
OldBloc.pData + pos + 2,
OldBloc.usLen - pos - 2);
GMEM_Free(OldBloc.pData);
OldBloc = NewBloc;
pos++;
}
else if (OldBloc.pData[pos + 1] < 0x80)
{
usIndex = OldBloc.pData[pos + 1];
rv = SearchDataByIndex(usIndex, pDictMemory, &RecordBloc);
if (rv != RV_SUCCESS)
{
GMEM_Free(OldBloc.pData);
return rv;
}
NewBloc.usLen = OldBloc.usLen - 2 + RecordBloc.usLen;
if ((NewBloc.pData = GMEM_Alloc(NewBloc.usLen)) == NULL_PTR)
{
GMEM_Free(OldBloc.pData);
return(RV_MALLOC_FAILED);
}
memcpy(NewBloc.pData, OldBloc.pData, pos);
memcpy(NewBloc.pData + pos, RecordBloc.pData, RecordBloc.usLen);
memcpy(NewBloc.pData + pos + RecordBloc.usLen,
OldBloc.pData + pos + 2,
OldBloc.usLen - pos - 2);
GMEM_Free(OldBloc.pData);
OldBloc = NewBloc;
pos += RecordBloc.usLen;
}
else
{
usIndex = ((OldBloc.pData[pos + 1] & 0x7F) << 8) + OldBloc.pData[pos + 2];
rv = SearchDataByIndex(usIndex, pDictMemory, &RecordBloc);
if (rv != RV_SUCCESS)
{
GMEM_Free(OldBloc.pData);
return rv;
}
NewBloc.usLen = OldBloc.usLen - 3 + RecordBloc.usLen;
if ((NewBloc.pData = GMEM_Alloc(NewBloc.usLen)) == NULL_PTR)
{
GMEM_Free(OldBloc.pData);
return(RV_MALLOC_FAILED);
}
memcpy(NewBloc.pData, OldBloc.pData, pos);
memcpy(NewBloc.pData + pos, RecordBloc.pData, RecordBloc.usLen);
memcpy(NewBloc.pData + pos + RecordBloc.usLen,
OldBloc.pData + pos + 3,
OldBloc.usLen - pos - 3);
GMEM_Free(OldBloc.pData);
OldBloc = NewBloc;
pos += RecordBloc.usLen;
}
}
else
{
pos++;
}
}
}
*pOutBloc = OldBloc;
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_GenericCompress(BLOC *pUncompBloc,
* BLOC *pCompBloc,
* BYTE AlgoId
* )
*
* Description : Effectue une compression statistique sur la donnée d'entrée en
* utilisant l'algorithme spécifié dans AlgoId.
*
* Remarks : Si l'algorithme spécifié n'est pas implémenté, renvoie la donnée
* originale.
*
* In : pUncompBloc : la donnée à compresser
* AlgoId : numéro de l'algorithme à employer
*
* Out : pCompBloc : la donnée compressée (mémoire allouée ici à libérer
* par la fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
*
*******************************************************************************/
int CC_GenericCompress(BLOC *pUncompBloc,
BLOC *pCompBloc,
BYTE AlgoId
)
{
switch(AlgoId)
{
#ifdef _ALGO_1
case ALGO_ACFX8 : /* Arithmetic coding, byte oriented, fixed model */
{
if (AcFx8_Encode(pUncompBloc, pCompBloc) != RV_SUCCESS)
{
return(RV_INVALID_DATA);
}
break;
}
#endif
#ifdef _ALGO_2
case ALGO_ACAD8 : /* Arithmetic coding, byte oriented, adaptative model */
{
if (AcAd8_Encode(pUncompBloc, pCompBloc) != RV_SUCCESS)
{
return(RV_INVALID_DATA);
}
break;
}
#endif
default :
{
if ((pCompBloc->pData = GMEM_Alloc(pUncompBloc->usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
pCompBloc->usLen = pUncompBloc->usLen;
memcpy(pCompBloc->pData, pUncompBloc->pData, pCompBloc->usLen);
break;
}
}
#ifdef _STUDY
fprintf(pfdLog, "Algo : %d | 0x%04x (%04d) -> 0x%04x (%04d)", AlgoId,
pUncompBloc->usLen, pUncompBloc->usLen,
pCompBloc->usLen, pCompBloc->usLen
);
if (pUncompBloc->usLen > pCompBloc->usLen)
{
fprintf(pfdLog, " | %d", pCompBloc->usLen - pUncompBloc->usLen);
}
fprintf(pfdLog, "\n");
#endif
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_GenericUncompress(BLOC *pCompBloc,
* BLOC *pUncompBloc,
* BYTE AlgoID
* )
*
* Description : Effectue une décompression statistique sur la donnée d'entrée en
* utilisant l'algorithme spécifié dans AlgoId.
*
* Remarks :
*
* In : pUncompBloc : la donnée à décompresser
* AlgoId : numéro de l'algorithme à employer
*
* Out : pCompBloc : la donnée décompressée (mémoire allouée ici à
* libérer par la fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* RV_INVALID_DATA : L'algorithme spécifié n'existe pas.
*
*******************************************************************************/
int CC_GenericUncompress(BLOC *pCompBloc,
BLOC *pUncompBloc,
BYTE AlgoId
)
{
switch(AlgoId)
{
case ALGO_NONE :
pUncompBloc->usLen = pCompBloc->usLen;
if ((pUncompBloc->pData = GMEM_Alloc(pUncompBloc->usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
memcpy(pUncompBloc->pData, pCompBloc->pData, pUncompBloc->usLen);
break;
#ifdef _ALGO_1
case ALGO_ACFX8 :
if (AcFx8_Decode(pCompBloc, pUncompBloc) != RV_SUCCESS)
{
return(RV_INVALID_DATA);
}
break;
#endif
#ifdef _ALGO_2
case ALGO_ACAD8 :
if (AcAd8_Decode(pCompBloc, pUncompBloc) != RV_SUCCESS)
{
return(RV_INVALID_DATA);
}
break;
#endif
default :
return(RV_INVALID_DATA);
break;
}
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_Encode_TBSCertificate(BLOC *pInBloc,
* BLOC *pOutBloc
* )
*
* Description : Encode une donnée de type TBSCertificate.
* Ceci consiste en l'éclatement en ses différents composants,
* leurs désenrobages Asn1 et leurs encodages respectifs, et la
* concaténation de ces résultats.
*
* Remarks : Certaines parties d'un TBSCertificate sont optionnelles. On
* détecte pour chacune d'elles si elle est présente et on
* l'indique dans des bits réservés d'un octet de contrôle placé
* en début du résultat encodé. Cet octet de contrôle contient
* également le numéro de version X.509 du certificat.
*
* In : pInBloc : la partie à encoder (champ Content)
*
* Out : pOutBloc : l'encodé (mémoire allouée ici à libérer par la
* fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Encode_TBSCertificate(BLOC *pInBloc,
BLOC *pOutBloc
)
{
ASN1
serialNumberPart,
signaturePart,
issuerPart,
validityPart,
subjectPart,
subjectPKInfoPart,
issuerUIDPart,
subjectUIDPart,
extensionsPart;
BLOC
serialNumberEncoded,
signatureEncoded,
issuerEncoded,
validityEncoded,
subjectEncoded,
subjectPKInfoEncoded,
issuerUIDEncoded,
subjectUIDEncoded,
extensionsEncoded;
BOOL
bVersionPresent = FALSE,
bIssuerUIDPresent = FALSE,
bSubjectUIDPresent = FALSE,
bExtensionsPresent = FALSE;
BYTE
*pCurrent;
int
rv;
USHORT
usVersion = 0;
/* Décomposition du tbsCertificate en ses différents composants */
pCurrent = pInBloc->pData;
if (pCurrent[0] == TAG_OPTION_VERSION)
{
/* On a alors A0 03 02 01 vv où vv est la version */
bVersionPresent = TRUE;
usVersion = pCurrent[4];
pCurrent += 5;
}
serialNumberPart.Asn1.pData = pCurrent;
rv = CC_ExtractContent(&serialNumberPart);
if (rv != RV_SUCCESS) return rv;
pCurrent = serialNumberPart.Content.pData + serialNumberPart.Content.usLen;
signaturePart.Asn1.pData = pCurrent;
rv = CC_ExtractContent(&signaturePart);
if (rv != RV_SUCCESS) return rv;
pCurrent = signaturePart.Content.pData + signaturePart.Content.usLen;
issuerPart.Asn1.pData = pCurrent;
rv = CC_ExtractContent(&issuerPart);
if (rv != RV_SUCCESS) return rv;
pCurrent = issuerPart.Content.pData + issuerPart.Content.usLen;
validityPart.Asn1.pData = pCurrent;
rv = CC_ExtractContent(&validityPart);
if (rv != RV_SUCCESS) return rv;
pCurrent = validityPart.Content.pData + validityPart.Content.usLen;
subjectPart.Asn1.pData = pCurrent;
rv = CC_ExtractContent(&subjectPart);
#ifdef _STUDY
// fprintf(pfdLog, "Subject : %d octets\n", subjectPart.Asn1.usLen);
#endif
if (rv != RV_SUCCESS) return rv;
pCurrent = subjectPart.Content.pData + subjectPart.Content.usLen;
subjectPKInfoPart.Asn1.pData = pCurrent;
rv = CC_ExtractContent(&subjectPKInfoPart);
if (rv != RV_SUCCESS) return rv;
pCurrent = subjectPKInfoPart.Content.pData + subjectPKInfoPart.Content.usLen;
if (pCurrent[0] == TAG_OPTION_ISSUER_UID)
{
bIssuerUIDPresent = TRUE;
issuerUIDPart.Asn1.pData = pCurrent;
rv = CC_ExtractContent(&issuerUIDPart);
if (rv != RV_SUCCESS) return rv;
pCurrent = issuerUIDPart.Content.pData + issuerUIDPart.Content.usLen;
}
if (pCurrent[0] == TAG_OPTION_SUBJECT_UID)
{
bSubjectUIDPresent = TRUE;
subjectUIDPart.Asn1.pData = pCurrent;
rv = CC_ExtractContent(&subjectUIDPart);
if (rv != RV_SUCCESS) return rv;
pCurrent = subjectUIDPart.Content.pData + subjectUIDPart.Content.usLen;
}
if (pCurrent[0] == TAG_OPTION_EXTENSIONS)
{
bExtensionsPresent = TRUE;
extensionsPart.Asn1.pData = pCurrent;
rv = CC_ExtractContent(&extensionsPart);
if (rv != RV_SUCCESS) return rv;
pCurrent = extensionsPart.Content.pData + extensionsPart.Content.usLen;
}
/* Encodages des différents composants et calcul de la longueur nécessaire */
/* Les pData des blocs *Encoded sont alloués par les fonctions CC_Encode_*.
Ils sont libérés dans cette fonction aprés usage */
serialNumberEncoded.pData = NULL;
signatureEncoded.pData = NULL;
issuerEncoded.pData = NULL;
validityEncoded.pData = NULL;
subjectEncoded.pData = NULL;
subjectPKInfoEncoded.pData= NULL;
issuerUIDEncoded.pData = NULL;
subjectUIDEncoded.pData = NULL;
extensionsEncoded.pData = NULL;
pOutBloc->usLen = 1;
rv = CC_Encode_CertificateSerialNumber(&serialNumberPart.Content, &serialNumberEncoded);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen += serialNumberEncoded.usLen;
rv = CC_Encode_AlgorithmIdentifier(&signaturePart.Content, &signatureEncoded);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen += signatureEncoded.usLen;
rv = CC_Encode_Name(&issuerPart.Content, &issuerEncoded);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen += issuerEncoded.usLen;
rv = CC_Encode_Validity(&validityPart.Content, &validityEncoded);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen += validityEncoded.usLen;
rv = CC_Encode_Name(&subjectPart.Content, &subjectEncoded);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen += subjectEncoded.usLen;
rv = CC_Encode_SubjectPKInfo(&subjectPKInfoPart.Content, &subjectPKInfoEncoded);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen += subjectPKInfoEncoded.usLen;
if (bIssuerUIDPresent == TRUE)
{
rv = CC_Encode_UniqueIdentifier(&issuerUIDPart.Content, &issuerUIDEncoded);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen += issuerUIDEncoded.usLen;
}
if (bSubjectUIDPresent == TRUE)
{
rv = CC_Encode_UniqueIdentifier(&subjectUIDPart.Content, &subjectUIDEncoded);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen += subjectUIDEncoded.usLen;
}
if (bExtensionsPresent == TRUE)
{
rv = CC_Encode_Extensions(&extensionsPart.Content, &extensionsEncoded);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen += extensionsEncoded.usLen;
}
/* Reconstruction à partir des composants */
/* A désallouer par le programme appelant */
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
pCurrent = pOutBloc->pData;
*pCurrent = 0x80 * (bVersionPresent == TRUE)
+ 0x40 * (bIssuerUIDPresent == TRUE)
+ 0x20 * (bSubjectUIDPresent == TRUE)
+ 0x10 * (bExtensionsPresent == TRUE)
+ usVersion;
pCurrent++;
memcpy(pCurrent, serialNumberEncoded.pData, serialNumberEncoded.usLen);
GMEM_Free(serialNumberEncoded.pData);
pCurrent += serialNumberEncoded.usLen;
memcpy(pCurrent, signatureEncoded.pData, signatureEncoded.usLen);
GMEM_Free(signatureEncoded.pData);
pCurrent += signatureEncoded.usLen;
memcpy(pCurrent, issuerEncoded.pData, issuerEncoded.usLen);
GMEM_Free(issuerEncoded.pData);
pCurrent += issuerEncoded.usLen;
memcpy(pCurrent, validityEncoded.pData, validityEncoded.usLen);
GMEM_Free(validityEncoded.pData);
pCurrent += validityEncoded.usLen;
memcpy(pCurrent, subjectEncoded.pData, subjectEncoded.usLen);
GMEM_Free(subjectEncoded.pData);
pCurrent += subjectEncoded.usLen;
memcpy(pCurrent, subjectPKInfoEncoded.pData, subjectPKInfoEncoded.usLen);
GMEM_Free(subjectPKInfoEncoded.pData);
pCurrent += subjectPKInfoEncoded.usLen;
if (bIssuerUIDPresent == TRUE)
{
memcpy(pCurrent, issuerUIDEncoded.pData, issuerUIDEncoded.usLen);
GMEM_Free(issuerUIDEncoded.pData);
pCurrent += issuerUIDEncoded.usLen;
}
if (bSubjectUIDPresent == TRUE)
{
memcpy(pCurrent, subjectUIDEncoded.pData, subjectUIDEncoded.usLen);
GMEM_Free(subjectUIDEncoded.pData);
pCurrent += subjectUIDEncoded.usLen;
}
if (bExtensionsPresent == TRUE)
{
memcpy(pCurrent, extensionsEncoded.pData, extensionsEncoded.usLen);
GMEM_Free(extensionsEncoded.pData);
pCurrent += extensionsEncoded.usLen;
}
return(RV_SUCCESS);
err:
GMEM_Free(serialNumberEncoded.pData);
GMEM_Free(signatureEncoded.pData);
GMEM_Free(issuerEncoded.pData);
GMEM_Free(validityEncoded.pData);
GMEM_Free(subjectEncoded.pData);
GMEM_Free(subjectPKInfoEncoded.pData);
GMEM_Free(issuerUIDEncoded.pData);
GMEM_Free(subjectUIDEncoded.pData);
GMEM_Free(extensionsEncoded.pData);
return rv;
}
/*******************************************************************************
* int CC_Encode_CertificateSerialNumber(BLOC *pInBloc,
* BLOC *pOutBloc
* )
*
* Description : Encode une donnée de type CertificateSerialNumber.
* Ceci consiste seulement en l'encodage brute (CC_RawEncode) de la
* donnée d'entrée.
*
* Remarks :
*
* In : pInBloc : la partie à encoder (champ Content)
*
* Out : pOutBloc : l'encodé (mémoire allouée ici à libérer par la
* fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Encode_CertificateSerialNumber(BLOC *pInBloc,
BLOC *pOutBloc
)
{
int
rv;
rv = CC_RawEncode(pInBloc, pOutBloc, TRUE);
if (rv != RV_SUCCESS) return rv;
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_Encode_AlgorithmIdentifier(BLOC *pInBloc,
* BLOC *pOutBloc
* )
*
* Description : Encode une donnée de type AlgorithmIdentifier.
* Ceci consiste en l'éclatement en ses différents composants,
* leurs désenrobages Asn1 et leurs encodages respectifs, et la
* concaténation de ces résultats.
*
* Remarks : bNullParam sert à coder sur un bit l'information qu'il n'y a pas
* de paramètre à l'algorithme. Cette information occupe toujours
* deux octets dans le certificat est vaut toujours {0x05, 0x00}.
* On utilise un dictionnaire statique (défini au début de ce
* source) pour remplacer le type d'algorithme par un index.
* Un octet de contrôle (en début du résultat) indique, ou bien que
* l'on n'a pas trouvé le type d'algo dans le dico (valeur 0xFF ->
* Encodage brut de la donnée d'entrée intégrale), ou bien un flag
* précisant s'il y a des paramètres et l'index du type d'algo.
*
* In : pInBloc : la partie à encoder (champ Content)
*
* Out : pOutBloc : l'encodé (mémoire allouée ici à libérer par la
* fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Encode_AlgorithmIdentifier(BLOC *pInBloc,
BLOC *pOutBloc
)
{
ASN1
AlgorithmPart,
ParametersPart;
BLOC
AlgorithmIdentifierEncoded,
ParametersAsn1Encoded;
BOOL
bFound,
bNoParam = FALSE,
bNullParam = FALSE;
int
rv;
USHORT
Index,
AlgoIndex;
AlgorithmPart.Asn1.pData = pInBloc->pData;
rv = CC_ExtractContent(&AlgorithmPart);
if (rv != RV_SUCCESS) return rv;
if (AlgorithmPart.Asn1.usLen == pInBloc->usLen)
{
bNoParam = TRUE;
bNullParam = FALSE;
}
else
{
ParametersPart.Asn1.pData = AlgorithmPart.Content.pData + AlgorithmPart.Content.usLen;
rv = CC_ExtractContent(&ParametersPart);
if (rv != RV_SUCCESS) return rv;
if (ParametersPart.Content.usLen == 0)
{
bNoParam = TRUE;
bNullParam = TRUE;
}
}
/* Recherche de l'identifiant de l'algorithme dans le dictionnaire */
Index = 0;
bFound = FALSE;
while ((bFound == FALSE) && (AlgorithmTypeDict[Index] != NULL))
{
if (!memcmp(AlgorithmTypeDict[Index],
AlgorithmPart.Content.pData,
AlgorithmPart.Content.usLen))
{
bFound = TRUE;
AlgoIndex = Index;
}
Index++;
}
/* Construction de l'encodage */
if (bFound == TRUE)
{
if (bNoParam == TRUE)
{
if (bNullParam == TRUE)
{
/* Si on a trouvé l'algorithme et il n'y a pas de paramètre */
pOutBloc->usLen = 1;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
return (RV_MALLOC_FAILED);
}
pOutBloc->pData[0] = (AlgoIndex | 0x80);
}
else
{
pOutBloc->usLen = 2;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
return (RV_MALLOC_FAILED);
}
pOutBloc->pData[0] = ABSENT_PARAMETER_CHAR;
pOutBloc->pData[1] = (BYTE) AlgoIndex;
}
}
else
{
/* Si on a trouvé l'algorithme et il y a des paramètres */
/* On RawEncode non pas le contenu des paramètres mais l'Asn1 entier
car on n'est pas sûr de l'encapsulage */
rv = CC_RawEncode(&(ParametersPart.Asn1), &ParametersAsn1Encoded, TRUE);
if (rv != RV_SUCCESS) return rv;
pOutBloc->usLen = 1 + ParametersAsn1Encoded.usLen;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
GMEM_Free(ParametersAsn1Encoded.pData);
return (RV_MALLOC_FAILED);
}
pOutBloc->pData[0] = (BYTE) AlgoIndex;
memcpy(&(pOutBloc->pData[1]),
ParametersAsn1Encoded.pData,
ParametersAsn1Encoded.usLen);
GMEM_Free(ParametersAsn1Encoded.pData);
}
}
else
{
/* Si on n'a pas trouvé l'algorithme dans le dictionnaire */
/* On RawEncode le contenu de AlgorithmIdentifier c'est à dire la
concaténation du asn1 de AlgorithmPart et du asn1 de ParametersPart */
rv = CC_RawEncode(pInBloc, &AlgorithmIdentifierEncoded, TRUE);
if (rv != RV_SUCCESS) return rv;
pOutBloc->usLen = 1 + AlgorithmIdentifierEncoded.usLen;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
GMEM_Free(AlgorithmIdentifierEncoded.pData);
return (RV_MALLOC_FAILED);
}
pOutBloc->pData[0] = ESCAPE_CHAR;
memcpy(&(pOutBloc->pData[1]),
AlgorithmIdentifierEncoded.pData,
AlgorithmIdentifierEncoded.usLen);
GMEM_Free(AlgorithmIdentifierEncoded.pData);
}
return (RV_SUCCESS);
}
/*******************************************************************************
* int CC_Encode_Name(BLOC *pInBloc,
* BLOC *pOutBloc
* )
*
* Description : Encode une donnée de type Name.
* Ceci consiste en l'éclatement en ses différents composants,
* leurs désenrobages Asn1 et leurs encodages respectifs, et la
* concaténation de ces résultats.
*
* Remarks : Un octet de contrôle (en début du résultat) indique le nombre
* de RelativeDistinguishedName dont est composé le Name.
*
* In : pInBloc : la partie à encoder (champ Content)
*
* Out : pOutBloc : l'encodé (mémoire allouée ici à libérer par la
* fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Encode_Name(BLOC *pInBloc,
BLOC *pOutBloc
)
{
ASN1
RDN[MAX_RDN];
BLOC
RDNEncoded[MAX_RDN];
BYTE
*pCurrent;
USHORT
i,
usNbRDN;
int
rv;
/* Décomposition du Name en ses différents RelativeDistinguishedName */
pCurrent = pInBloc->pData;
usNbRDN = 0;
while (pCurrent < pInBloc->pData + pInBloc->usLen)
{
RDN[usNbRDN].Asn1.pData = pCurrent;
rv = CC_ExtractContent(&(RDN[usNbRDN]));
if (rv != RV_SUCCESS) return rv;
pCurrent = RDN[usNbRDN].Content.pData + RDN[usNbRDN].Content.usLen;
usNbRDN++;
}
ASSERT(pCurrent == pInBloc->pData + pInBloc->usLen);
/* Encodages des différents composants et calcul de la longueur nécessaire */
for (i = 0; i < usNbRDN; i++)
{
RDNEncoded[i].pData = NULL;
}
pOutBloc->usLen = 1;
for (i = 0; i < usNbRDN; i++)
{
rv = CC_Encode_RDN(&RDN[i].Content, &RDNEncoded[i]);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen += RDNEncoded[i].usLen;
}
/* Reconstruction à partir des composants */
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
pCurrent = pOutBloc->pData;
*pCurrent = (BYTE) usNbRDN;
pCurrent++;
for (i = 0; i < usNbRDN; i++)
{
memcpy(pCurrent, RDNEncoded[i].pData, RDNEncoded[i].usLen);
GMEM_Free(RDNEncoded[i].pData);
pCurrent += RDNEncoded[i].usLen;
}
return(RV_SUCCESS);
err:
for (i = 0; i < usNbRDN; i++)
{
GMEM_Free(RDNEncoded[i].pData);
}
return (rv);
}
/*******************************************************************************
* int CC_Encode_RDN(BLOC *pInBloc,
* BLOC *pOutBloc
* )
*
* Description : Encode une donnée de type RelativeDistinguishedName (RDN).
* Ceci consiste en l'éclatement en ses différents composants,
* leurs désenrobages Asn1 et leurs encodages respectifs, et la
* concaténation de ces résultats.
*
* Remarks : Un octet de contrôle (en début du résultat) indique le nombre
* de AttributeValueAssertion dont est composé le RDN.
*
* In : pInBloc : la partie à encoder (champ Content)
*
* Out : pOutBloc : l'encodé (mémoire allouée ici à libérer par la
* fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Encode_RDN(BLOC *pInBloc,
BLOC *pOutBloc
)
{
ASN1
AVA[MAX_AVA];
BLOC
AVAEncoded[MAX_AVA];
BYTE
*pCurrent;
USHORT
i,
usNbAVA;
int
rv;
/* Décomposition du RDN en ses différents AVA */
pCurrent = pInBloc->pData;
usNbAVA = 0;
while (pCurrent < pInBloc->pData + pInBloc->usLen)
{
AVA[usNbAVA].Asn1.pData = pCurrent;
rv = CC_ExtractContent(&(AVA[usNbAVA]));
if (rv != RV_SUCCESS) return rv;
pCurrent = AVA[usNbAVA].Content.pData + AVA[usNbAVA].Content.usLen;
usNbAVA++;
}
ASSERT(pCurrent == pInBloc->pData + pInBloc->usLen);
/* Encodages des différents composants et calcul de la longueur nécessaire */
for (i = 0; i < usNbAVA; i++)
{
AVAEncoded[i].pData = NULL;
}
pOutBloc->usLen = 1;
for (i = 0; i < usNbAVA; i++)
{
rv = CC_Encode_AVA(&AVA[i].Content, &AVAEncoded[i]);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen += AVAEncoded[i].usLen;
}
/* Reconstruction à partir des composants */
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
pCurrent = pOutBloc->pData;
*pCurrent = (BYTE) usNbAVA;
pCurrent++;
for (i = 0; i < usNbAVA; i++)
{
memcpy(pCurrent, AVAEncoded[i].pData, AVAEncoded[i].usLen);
GMEM_Free(AVAEncoded[i].pData);
pCurrent += AVAEncoded[i].usLen;
}
return(RV_SUCCESS);
err:
for (i = 0; i < usNbAVA; i++)
{
GMEM_Free(AVAEncoded[i].pData);
}
return(rv);
}
/*******************************************************************************
* int CC_Encode_AVA(BLOC *pInBloc,
* BLOC *pOutBloc
* )
*
* Description : Encode une donnée de type AttributeValueAssertion (AVA).
* Ceci consiste en l'éclatement en ses différents composants,
* leurs désenrobages Asn1 et leurs encodages respectifs, et la
* concaténation de ces résultats.
*
* Remarks : On utilise un dictionnaire statique (défini au début de ce
* source) pour remplacer le type d'attribut par un index.
* Un octet de contrôle (en début du résultat) indique, ou bien que
* l'on n'a pas trouvé le type d'attribut dans le dico (0xFF)
* ou l'index du type d'attribut.
* On ne code pas le Content de AttributeValue mais son Asn1 car on
* n'est pas sûr du tag employé.
*
* In : pInBloc : la partie à encoder (champ Content)
*
* Out : pOutBloc : l'encodé (mémoire allouée ici à libérer par la
* fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Encode_AVA(BLOC *pInBloc,
BLOC *pOutBloc
)
{
ASN1
AttributeTypePart,
AttributeValuePart;
BLOC
AttributeTypeEncoded,
AttributeValueEncoded;
BOOL
bFound;
USHORT
Index,
AttributeTypeIndex;
int
rv;
/* Décomposition */
AttributeTypePart.Asn1.pData = pInBloc->pData;
rv = CC_ExtractContent(&AttributeTypePart);
if (rv != RV_SUCCESS) return rv;
AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+ AttributeTypePart.Content.usLen;
rv = CC_ExtractContent(&AttributeValuePart); /* Pas nécessaire */
if (rv != RV_SUCCESS) return rv;
/* Recherche de l'identifiant de l'AttributeType dans le dictionnaire */
Index = 0;
bFound = FALSE;
while((bFound == FALSE) && (AttributeTypeDict[Index] != NULL))
{
if (!memcmp(AttributeTypeDict[Index],
AttributeTypePart.Content.pData,
AttributeTypePart.Content.usLen))
{
bFound = TRUE;
AttributeTypeIndex = Index;
}
Index++;
}
/* Construction de l'encodage */
/* Attention : on encode aussi l'enrobage de AttributeValue ! */
if (bFound == TRUE)
{
/* Il nous faut la longueur enrobage compris mais cette ligne est-elle
vraiment nécessaire ? */
AttributeValuePart.Asn1.usLen = (unsigned short) (DWORD)((pInBloc->pData + pInBloc->usLen)
- AttributeValuePart.Asn1.pData);
rv = CC_RawEncode(&(AttributeValuePart.Asn1), &AttributeValueEncoded, TRUE);
if (rv != RV_SUCCESS) return rv;
pOutBloc->usLen = 1 + AttributeValueEncoded.usLen;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
GMEM_Free(AttributeValueEncoded.pData);
return(RV_MALLOC_FAILED);
}
pOutBloc->pData[0] = (BYTE) AttributeTypeIndex;
memcpy(&(pOutBloc->pData[1]), AttributeValueEncoded.pData, AttributeValueEncoded.usLen);
GMEM_Free(AttributeValueEncoded.pData);
}
else
{
/* Si on n'a pas trouvé l'attribut dans le dictionnaire */
rv = CC_RawEncode(&(AttributeTypePart.Content), &AttributeTypeEncoded, TRUE);
if (rv != RV_SUCCESS) return rv;
rv = CC_RawEncode(&(AttributeValuePart.Asn1), &AttributeValueEncoded, TRUE);
if (rv != RV_SUCCESS)
{
GMEM_Free(AttributeTypeEncoded.pData);
return rv;
}
pOutBloc->usLen = 1
+ AttributeTypeEncoded.usLen
+ AttributeValueEncoded.usLen;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
GMEM_Free(AttributeTypeEncoded.pData);
GMEM_Free(AttributeValueEncoded.pData);
return(RV_MALLOC_FAILED);
}
pOutBloc->pData[0] = ESCAPE_CHAR;
memcpy(&(pOutBloc->pData[1]),
AttributeTypeEncoded.pData,
AttributeTypeEncoded.usLen);
memcpy(&(pOutBloc->pData[1 + AttributeTypeEncoded.usLen]),
AttributeValueEncoded.pData,
AttributeValueEncoded.usLen);
GMEM_Free(AttributeTypeEncoded.pData);
GMEM_Free(AttributeValueEncoded.pData);
}
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_Encode_Validity(BLOC *pInBloc,
* BLOC *pOutBloc
* )
*
* Description : Encode une donnée de type Validity.
* Ceci consiste en l'éclatement en ses différents composants,
* leurs désenrobages Asn1 et leurs encodages respectifs, et la
* concaténation de ces résultats.
*
* Remarks : Un octet de contrôle (en début du résultat) indique les formats
* des deux parties notBefore et notAfter.
*
* In : pInBloc : la partie à encoder (champ Content)
*
* Out : pOutBloc : l'encodé (mémoire allouée ici à libérer par la
* fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Encode_Validity(BLOC *pInBloc,
BLOC *pOutBloc
)
{
ASN1
notBeforePart,
notAfterPart;
BLOC
notBeforeEncoded,
notAfterEncoded;
BYTE
notBeforeFormat,
notAfterFormat,
*pCurrent;
int
rv;
/* Décomposition */
pCurrent = pInBloc->pData;
notBeforePart.Asn1.pData = pCurrent;
rv = CC_ExtractContent(&notBeforePart);
if (rv != RV_SUCCESS) return rv;
pCurrent = notBeforePart.Content.pData + notBeforePart.Content.usLen;
notAfterPart.Asn1.pData = pCurrent;
rv = CC_ExtractContent(&notAfterPart);
if (rv != RV_SUCCESS) return rv;
pCurrent = notAfterPart.Content.pData + notAfterPart.Content.usLen;
/* Encodages des différents composants et calcul de la longueur nécessaire */
pOutBloc->usLen = 1;
rv = CC_Encode_UTCTime(&notBeforePart.Content, &notBeforeEncoded, &notBeforeFormat);
if (rv != RV_SUCCESS) return rv;
pOutBloc->usLen += notBeforeEncoded.usLen;
rv = CC_Encode_UTCTime(&notAfterPart.Content, &notAfterEncoded, &notAfterFormat);
if (rv != RV_SUCCESS)
{
GMEM_Free(notBeforeEncoded.pData);
return rv;
}
pOutBloc->usLen += notAfterEncoded.usLen;
/* Reconstruction à partir des composants */
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
GMEM_Free(notBeforeEncoded.pData);
GMEM_Free(notAfterEncoded.pData);
return(RV_MALLOC_FAILED);
}
pCurrent = pOutBloc->pData;
*pCurrent = (notBeforeFormat << 4) + notAfterFormat;
pCurrent++;
memcpy(pCurrent, notBeforeEncoded.pData, notBeforeEncoded.usLen);
GMEM_Free(notBeforeEncoded.pData);
pCurrent += notBeforeEncoded.usLen;
memcpy(pCurrent, notAfterEncoded.pData, notAfterEncoded.usLen);
GMEM_Free(notAfterEncoded.pData);
pCurrent += notAfterEncoded.usLen;
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_Encode_UTCTime(BLOC *pInBloc,
* BLOC *pOutBloc,
* BYTE *pFormat
* )
*
* Description : Encode une donnée de type UTCTime.
* Suivant le format détecté, l'encodage consiste en :
* - sur 32 bits : le nombre de minutes ou de secondes depuis une
* date de référence.
* - sur 16 bits : le nombre de minutes de décalage UTC
* s'il y a lieu.
*
* Remarks :
*
* In : pInBloc : la partie à encoder (champ Content)
*
* Out : pOutBloc : l'encodé (mémoire allouée ici à libérer par la
* fonction appelante)
* pFormat : indique au quel format était la donnée d'entrée
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Encode_UTCTime(BLOC *pInBloc,
BLOC *pOutBloc,
BYTE *pFormat
)
{
BYTE
*pData;
ULONG
ulNbMinute,
ulNbSecond;
USHORT
usNbDeltaMinute,
usYear,
usMonth,
usDay,
usHour,
usMinute,
usSecond,
usDeltaHour,
usDeltaMinute,
usDayInYear;
pData = pInBloc->pData;
/* Calcul du nombre de minutes */
usYear = 10 * (pData[0] - '0') + (pData[1] - '0');
usMonth = 10 * (pData[2] - '0') + (pData[3] - '0');
usDay = 10 * (pData[4] - '0') + (pData[5] - '0');
usHour = 10 * (pData[6] - '0') + (pData[7] - '0');
usMinute = 10 * (pData[8] - '0') + (pData[9] - '0');
ASSERT((usYear >= 0) && (usYear <= 99));
ASSERT((usMonth >= 1) && (usMonth <= 12));
ASSERT((usDay >= 1) && (usDay <= 31));
ASSERT((usHour >= 0) && (usHour <= 23));
ASSERT((usMinute >= 0) && (usMinute <= 59));
/* Le nombre de jours dans l'année vaut 0 le 1er janvier */
usDayInYear = NbDaysInMonth[usMonth - 1] + (usDay - 1);
if (((usYear % 4) == 0) && (usMonth >= 3)) usDayInYear++;
/* L'année 00 est comptée bissextile ci-dessous */
/* L'année courante si elle l'est a déjà été comptée dans usDayInYear */
/*
Problème sur l'évaluation de (usYear - 1) / 4 :
usYear = 8 -> 1
usYear = 4 -> 0
usYear = 0 -> 0 !!
ulNbMinute = usYear * UTCT_MINUTE_IN_YEAR
+ (1 + (usYear - 1) / 4) * UTCT_MINUTE_IN_DAY
+ usDayInYear * UTCT_MINUTE_IN_DAY
+ usHour * UTCT_MINUTE_IN_HOUR
+ usMinute;
*/
ulNbMinute = usYear * UTCT_MINUTE_IN_YEAR
+ (usYear + 3) / 4 * UTCT_MINUTE_IN_DAY // Années bissextiles
+ usDayInYear * UTCT_MINUTE_IN_DAY
+ usHour * UTCT_MINUTE_IN_HOUR
+ usMinute;
/* Le format et la suite des calculs en fonction de la longueur */
switch(pInBloc->usLen)
{
case 11 :
*pFormat = UTCT_YYMMDDhhmmZ;
ASSERT(pData[10] == 'Z');
pOutBloc->usLen = 4;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
*(ULONG *)pOutBloc->pData = ulNbMinute;
break;
case 13 :
*pFormat = UTCT_YYMMDDhhmmssZ;
usSecond = 10 * (pData[10] - '0') + (pData[11] - '0');
ASSERT((usSecond >= 0) && (usSecond <= 59));
ASSERT(pData[12] == 'Z');
ulNbSecond = 60 * ulNbMinute + usSecond;
pOutBloc->usLen = 4;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
*(ULONG *)pOutBloc->pData = ulNbSecond;
break;
case 15 :
if (pData[10] == '+')
{
*pFormat = UTCT_YYMMDDhhmmphhmm;
}
else if (pData[10] == '-')
{
*pFormat = UTCT_YYMMDDhhmmmhhmm;
}
else
{
return(RV_INVALID_DATA);
}
usDeltaHour = 10 * (pData[11] - '0') + (pData[12] - '0');
usDeltaMinute = 10 * (pData[13] - '0') + (pData[14] - '0');
ASSERT((usDeltaHour >= 0) && (usDeltaHour <= 23));
ASSERT((usDeltaMinute >= 0) && (usDeltaMinute <= 59));
usNbDeltaMinute = 60 * usDeltaHour + usDeltaMinute;
pOutBloc->usLen = 4 + 2;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
*(ULONG *)pOutBloc->pData = ulNbMinute;
*(USHORT *)(pOutBloc->pData + sizeof(ulNbMinute)) = usNbDeltaMinute;
break;
case 17 :
if (pData[12] == '+')
{
*pFormat = UTCT_YYMMDDhhmmphhmm;
}
else if (pData[12] == '-')
{
*pFormat = UTCT_YYMMDDhhmmmhhmm;
}
else
{
return(RV_INVALID_DATA);
}
usSecond = 10 * (pData[10] - '0') + (pData[11] - '0');
ASSERT((usSecond >= 0) && (usSecond <= 59));
ulNbSecond = 60 * ulNbMinute + usSecond;
usDeltaHour = 10 * (pData[13] - '0') + (pData[14] - '0');
usDeltaMinute = 10 * (pData[15] - '0') + (pData[16] - '0');
ASSERT((usDeltaHour >= 0) && (usDeltaHour <= 23));
ASSERT((usDeltaMinute >= 0) && (usDeltaMinute <= 59));
usNbDeltaMinute = 60 * usDeltaHour + usDeltaMinute;
pOutBloc->usLen = 4 + 2;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
*(ULONG *)pOutBloc->pData = ulNbSecond;
*(USHORT *)(pOutBloc->pData + sizeof(ulNbSecond)) = usNbDeltaMinute;
break;
default :
return(RV_INVALID_DATA);
}
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_Encode_SubjectPKInfo(BLOC *pInBloc,
* BLOC *pOutBloc
* )
*
* Description : Encode une donnée de type SubjectPublicKeyInfo.
* Ceci consiste en l'éclatement en ses différents composants,
* leurs désenrobages Asn1 et leurs encodages respectifs, et la
* concaténation de ces résultats.
*
* Remarks :
*
* In : pInBloc : la partie à encoder (champ Content)
*
* Out : pOutBloc : l'encodé (mémoire allouée ici à libérer par la
* fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Encode_SubjectPKInfo(BLOC *pInBloc,
BLOC *pOutBloc
)
{
ASN1
algorithmPart,
subjectPKPart;
BLOC
algorithmEncoded,
subjectPKEncoded;
BYTE
// *pData,
*pCurrent;
int
rv;
/* Décomposition du SubjectPKInfo en ses différents composants */
pCurrent = pInBloc->pData;
algorithmPart.Asn1.pData = pCurrent;
rv = CC_ExtractContent(&algorithmPart);
if (rv != RV_SUCCESS) return rv;
pCurrent = algorithmPart.Content.pData + algorithmPart.Content.usLen;
subjectPKPart.Asn1.pData = pCurrent;
rv = CC_ExtractContent(&subjectPKPart);
if (rv != RV_SUCCESS) return rv;
pCurrent = subjectPKPart.Content.pData + subjectPKPart.Content.usLen;
/* Encodages des différents composants et calcul de la longueur nécessaire */
pOutBloc->usLen = 0;
rv = CC_Encode_AlgorithmIdentifier(&algorithmPart.Content, &algorithmEncoded);
if (rv != RV_SUCCESS) return rv;
pOutBloc->usLen += algorithmEncoded.usLen;
#ifdef _TRICKY_COMPRESSION
/* Ne pas faire le RawEncode permet de gagner l'octet 0xFF et éventuellement plus */
#ifdef _OPT_HEADER
if (subjectPKPart.Content.usLen < 0x80)
{
if ((pData = GMEM_Alloc(pInBloc->usLen + 1)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
else
{
pData[0] = subjectPKPart.Content.usLen;
memcpy(&pData[1],
subjectPKPart.Content.pData,
subjectPKPart.Content.usLen);
subjectPKEncoded.usLen = subjectPKPart.Content.usLen + 1;
subjectPKEncoded.pData = pData;
}
pOutBloc->usLen += subjectPKEncoded.usLen;
}
else
{
if ((pData = GMEM_Alloc(pInBloc->usLen + 2)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
else
{
pData[0] = 0x80 | (subjectPKPart.Content.usLen >> 8);
pData[1] = subjectPKPart.Content.usLen & 0x00FF;
memcpy(&pData[2],
subjectPKPart.Content.pData,
subjectPKPart.Content.usLen);
subjectPKEncoded.usLen = subjectPKPart.Content.usLen + 2;
subjectPKEncoded.pData = pData;
}
pOutBloc->usLen += subjectPKEncoded.usLen;
}
#else /* _OPT_HEADER */
if ((pData = GMEM_Alloc(pInBloc->usLen + 2)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
else
{
pData[0] = subjectPKPart.Content.usLen >> 8;
pData[1] = subjectPKPart.Content.usLen & 0x00FF;
memcpy(&pData[2],
subjectPKPart.Content.pData,
subjectPKPart.Content.usLen);
subjectPKEncoded.usLen = subjectPKPart.Content.usLen + 2;
subjectPKEncoded.pData = pData;
}
pOutBloc->usLen += subjectPKEncoded.usLen;
#endif
#else /* _TRICKY_COMPRESSION */
rv = CC_RawEncode(&subjectPKPart.Content, &subjectPKEncoded, FALSE);
if (rv != RV_SUCCESS)
{
GMEM_Free(algorithmEncoded.pData);
return rv;
}
pOutBloc->usLen += subjectPKEncoded.usLen;
#endif
/* Reconstruction à partir des composants */
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
GMEM_Free(algorithmEncoded.pData);
GMEM_Free(subjectPKEncoded.pData);
return(RV_MALLOC_FAILED);
}
pCurrent = pOutBloc->pData;
memcpy(pCurrent, algorithmEncoded.pData, algorithmEncoded.usLen);
GMEM_Free(algorithmEncoded.pData);
pCurrent += algorithmEncoded.usLen;
memcpy(pCurrent, subjectPKEncoded.pData, subjectPKEncoded.usLen);
GMEM_Free(subjectPKEncoded.pData);
pCurrent += subjectPKEncoded.usLen;
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_Encode_UniqueIdentifier(BLOC *pInBloc,
* BLOC *pOutBloc
* )
*
* Description : Encode une donnée de type UniqueIdentifier.
* Ceci consiste seulement en l'encodage brute (CC_RawEncode) de la
* donnée d'entrée.
*
* Remarks :
*
* In : pInBloc : la partie à encoder (champ Content)
*
* Out : pOutBloc : l'encodé (mémoire allouée ici à libérer par la
* fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Encode_UniqueIdentifier(BLOC *pInBloc,
BLOC *pOutBloc
)
{
int
rv;
rv = CC_RawEncode(pInBloc, pOutBloc, TRUE);
if (rv != RV_SUCCESS) return rv;
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_Encode_Extensions(BLOC *pInBloc,
* BLOC *pOutBloc
* )
*
* Description : Encode une donnée de type Extensions.
* Ceci consiste seulement en l'encodage brute (CC_RawEncode) de la
* donnée d'entrée.
*
* Remarks : Un désenrobage supplémentaire (context specific) est requis.
* Un octet de contrôle (en début du résultat) indique le nombre
* de Extension dont est composé le Extensions.
*
* In : pInBloc : la partie à encoder (champ Content)
*
* Out : pOutBloc : l'encodé (mémoire allouée ici à libérer par la
* fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Encode_Extensions(BLOC *pInBloc,
BLOC *pOutBloc
)
{
ASN1
ExtensionPart[MAX_EXTENSION],
InInAsn1;
BLOC
ExtensionEncoded[MAX_EXTENSION],
*pInInBloc;
BYTE
*pCurrent;
int
rv;
USHORT
i,
usNbExtension;
/* On enlève l'enrobage 'context specific' supplémentaire */
/* et on travaille avec pInInBloc au lieu de pInBloc */
InInAsn1.Asn1.pData = pInBloc->pData;
rv = CC_ExtractContent(&InInAsn1);
if (rv != RV_SUCCESS) return rv;
pInInBloc = &(InInAsn1.Content);
/* Décomposition de Extensions en ses différents Extension */
pCurrent = pInInBloc->pData;
usNbExtension = 0;
while (pCurrent < pInInBloc->pData + pInInBloc->usLen)
{
ExtensionPart[usNbExtension].Asn1.pData = pCurrent;
rv = CC_ExtractContent(&(ExtensionPart[usNbExtension]));
if (rv != RV_SUCCESS) return rv;
pCurrent = ExtensionPart[usNbExtension].Content.pData
+ ExtensionPart[usNbExtension].Content.usLen;
usNbExtension++;
}
ASSERT(pCurrent == pInInBloc->pData + pInInBloc->usLen);
/* Encodages des différents composants et calcul de la longueur nécessaire */
for (i = 0; i < usNbExtension; i++)
{
ExtensionEncoded[i].pData = NULL;
}
pOutBloc->usLen = 1;
for (i = 0; i < usNbExtension; i++)
{
rv = CC_Encode_Extension(&ExtensionPart[i].Content, &ExtensionEncoded[i]);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen += ExtensionEncoded[i].usLen;
}
/* Reconstruction à partir des composants */
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
pCurrent = pOutBloc->pData;
*pCurrent = (BYTE) usNbExtension;
pCurrent++;
for (i = 0; i < usNbExtension; i++)
{
memcpy(pCurrent, ExtensionEncoded[i].pData, ExtensionEncoded[i].usLen);
GMEM_Free(ExtensionEncoded[i].pData);
pCurrent += ExtensionEncoded[i].usLen;
}
return(RV_SUCCESS);
err:
for (i = 0; i < usNbExtension; i++)
{
GMEM_Free(ExtensionEncoded[i].pData);
}
return(rv);
}
/*******************************************************************************
* int CC_Encode_Extension(BLOC *pInBloc,
* BLOC *pOutBloc
* )
*
* Description : Encode une donnée de type Extension.
* Ceci consiste seulement en l'encodage brute (CC_RawEncode) de la
* donnée d'entrée.
*
* Remarks :
*
* In : pInBloc : la partie à encoder (champ Content)
*
* Out : pOutBloc : l'encodé (mémoire allouée ici à libérer par la
* fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Encode_Extension(BLOC *pInBloc,
BLOC *pOutBloc
)
{
int
rv;
rv = CC_RawEncode(pInBloc, pOutBloc, TRUE);
if (rv != RV_SUCCESS) return rv;
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_Encode_Signature(BLOC *pInBloc,
* BLOC *pOutBloc
* )
*
* Description : Encode la signature du certificat.
* Ceci consiste seulement en l'encodage brute (CC_RawEncode) de la
* donnée d'entrée.
*
* Remarks : On peut éviter de tenter de compresser (CC_RawEncode) si on
* estime que cela ne sera pas efficace (donnée aléatoire).
* Cela permet de gagner un octet (0xFF) pour les données de taille
* supérieure à 30 octets (cas général).
*
* In : pInBloc : la partie à encoder (champ Content)
*
* Out : pOutBloc : l'encodé (mémoire allouée ici à libérer par la
* fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Encode_Signature(BLOC *pInBloc,
BLOC *pOutBloc
)
{
// BYTE
// *pData;
int
rv;
#ifdef _TRICKY_COMPRESSION
/* Ne pas faire le RawEncode permet de gagner l'octet 0xFF */
#ifdef _OPT_HEADER
if (pInBloc->usLen < 0x80)
{
if ((pData = GMEM_Alloc(pInBloc->usLen + 1)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
else
{
pData[0] = pInBloc->usLen;
memcpy(&pData[1], pInBloc->pData, pInBloc->usLen);
pOutBloc->usLen = pInBloc->usLen + 1;
pOutBloc->pData = pData;
}
}
else
{
if ((pData = GMEM_Alloc(pInBloc->usLen + 2)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
else
{
pData[0] = 0x80 | (pInBloc->usLen >> 8);
pData[1] = pInBloc->usLen & 0x00FF;
memcpy(&pData[2], pInBloc->pData, pInBloc->usLen);
pOutBloc->usLen = pInBloc->usLen + 2;
pOutBloc->pData = pData;
}
}
#else /* _OPT_HEADER */
if ((pData = GMEM_Alloc(pInBloc->usLen + 2)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
else
{
pData[0] = pInBloc->usLen >> 8;
pData[1] = pInBloc->usLen & 0x00FF;
memcpy(&pData[2], pInBloc->pData, pInBloc->usLen);
pOutBloc->usLen = pInBloc->usLen + 2;
pOutBloc->pData = pData;
}
#endif
#else /* _TRICKY_COMPRESSION */
rv = CC_RawEncode(pInBloc, pOutBloc, TRUE);
if (rv != RV_SUCCESS) return rv;
#endif
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_Decode_TBSCertificate(BYTE *pInData,
* BLOC *pOutBloc,
* USHORT *pLength
* )
*
* Description : Décode une donnée de type TBSCertificate.
* Ceci consiste en le décodage des différentes parties encodées
* successives, leurs enrobages respectifs (tags uniquement
* par la spec X.509), et la concaténation de ces résultats.
*
* Remarks :
*
* In : pInBloc : la partie à décoder (champ Content)
*
* Out : pOutBloc : le décodé (mémoire allouée ici à libérer par la
* fonction appelante)
* pLength : la longueur de données encodés utilisée
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Decode_TBSCertificate(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
)
{
ASN1
serialNumberPart,
signaturePart,
issuerPart,
validityPart,
subjectPart,
subjectPKInfoPart,
issuerUIDPart,
subjectUIDPart,
extensionsPart;
BOOL
bVersionPresent,
bIssuerUIDPresent,
bSubjectUIDPresent,
bExtensionsPresent;
BYTE
*pCurrent;
int
rv;
USHORT
usVersion = 0,
Length;
serialNumberPart.Asn1.pData = NULL;
signaturePart.Asn1.pData = NULL;
issuerPart.Asn1.pData = NULL;
validityPart.Asn1.pData = NULL;
subjectPart.Asn1.pData = NULL;
subjectPKInfoPart.Asn1.pData = NULL;
issuerUIDPart.Asn1.pData = NULL;
subjectUIDPart.Asn1.pData = NULL;
extensionsPart.Asn1.pData = NULL;
pCurrent = pInData;
bVersionPresent = ((*pCurrent & 0x80) != 0);
bIssuerUIDPresent = ((*pCurrent & 0x40) != 0);
bSubjectUIDPresent = ((*pCurrent & 0x20) != 0);
bExtensionsPresent = ((*pCurrent & 0x10) != 0);
usVersion = *pCurrent & 0x03;
pCurrent++;
rv = CC_Decode_CertificateSerialNumber(pCurrent, &(serialNumberPart.Content), &Length);
if (rv != RV_SUCCESS) goto err;
serialNumberPart.Tag = TAG_INTEGER;
rv = CC_BuildAsn1(&serialNumberPart);
GMEM_Free(serialNumberPart.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
rv = CC_Decode_AlgorithmIdentifier(pCurrent, &(signaturePart.Content), &Length);
if (rv != RV_SUCCESS) goto err;
signaturePart.Tag = TAG_SEQUENCE;
rv = CC_BuildAsn1(&signaturePart);
GMEM_Free(signaturePart.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
rv = CC_Decode_Name(pCurrent, &(issuerPart.Content), &Length);
if (rv != RV_SUCCESS) goto err;
issuerPart.Tag = TAG_SEQUENCE_OF;
rv = CC_BuildAsn1(&issuerPart);
GMEM_Free(issuerPart.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
rv = CC_Decode_Validity(pCurrent, &(validityPart.Content), &Length);
if (rv != RV_SUCCESS) goto err;
validityPart.Tag = TAG_SEQUENCE;
rv = CC_BuildAsn1(&validityPart);
GMEM_Free(validityPart.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
rv = CC_Decode_Name(pCurrent, &(subjectPart.Content), &Length);
if (rv != RV_SUCCESS) goto err;
subjectPart.Tag = TAG_SEQUENCE_OF;
rv = CC_BuildAsn1(&subjectPart);
GMEM_Free(subjectPart.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
rv = CC_Decode_SubjectPKInfo(pCurrent, &(subjectPKInfoPart.Content), &Length);
if (rv != RV_SUCCESS) goto err;
subjectPKInfoPart.Tag = TAG_SEQUENCE;
rv = CC_BuildAsn1(&subjectPKInfoPart);
GMEM_Free(subjectPKInfoPart.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
if (bIssuerUIDPresent == TRUE)
{
rv = CC_Decode_UniqueIdentifier(pCurrent, &(issuerUIDPart.Content), &Length);
if (rv != RV_SUCCESS) goto err;
issuerUIDPart.Tag = TAG_OPTION_ISSUER_UID;
rv = CC_BuildAsn1(&issuerUIDPart);
GMEM_Free(issuerUIDPart.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
}
if (bSubjectUIDPresent == TRUE)
{
rv = CC_Decode_UniqueIdentifier(pCurrent, &(subjectUIDPart.Content), &Length);
if (rv != RV_SUCCESS) goto err;
subjectUIDPart.Tag = TAG_OPTION_SUBJECT_UID;
rv = CC_BuildAsn1(&subjectUIDPart);
GMEM_Free(subjectUIDPart.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
}
if (bExtensionsPresent == TRUE)
{
rv = CC_Decode_Extensions(pCurrent, &(extensionsPart.Content), &Length);
if (rv != RV_SUCCESS) goto err;
extensionsPart.Tag = TAG_OPTION_EXTENSIONS;
rv = CC_BuildAsn1(&extensionsPart);
GMEM_Free(extensionsPart.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
}
*pLength = (unsigned short)(DWORD) (pCurrent - pInData);
/* Calcul de la longueur du tbsCertificate décodé et allocation */
pOutBloc->usLen = (bVersionPresent ? 5 : 0)
+ serialNumberPart.Asn1.usLen
+ signaturePart.Asn1.usLen
+ issuerPart.Asn1.usLen
+ validityPart.Asn1.usLen
+ subjectPart.Asn1.usLen
+ subjectPKInfoPart.Asn1.usLen
+ (bIssuerUIDPresent ? issuerUIDPart.Asn1.usLen : 0)
+ (bSubjectUIDPresent ? subjectUIDPart.Asn1.usLen : 0)
+ (bExtensionsPresent ? extensionsPart.Asn1.usLen : 0);
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
/* Reconstruction du tbsCertificate décodé */
pCurrent = pOutBloc->pData;
if (bVersionPresent == TRUE)
{
pCurrent[0] = TAG_OPTION_VERSION;
pCurrent[1] = 0x03;
pCurrent[2] = 0x02;
pCurrent[3] = 0x01;
pCurrent[4] = (BYTE)usVersion;
pCurrent += 5;
}
memcpy(pCurrent, serialNumberPart.Asn1.pData, serialNumberPart.Asn1.usLen);
GMEM_Free(serialNumberPart.Asn1.pData);
pCurrent += serialNumberPart.Asn1.usLen;
memcpy(pCurrent, signaturePart.Asn1.pData, signaturePart.Asn1.usLen);
GMEM_Free(signaturePart.Asn1.pData);
pCurrent += signaturePart.Asn1.usLen;
memcpy(pCurrent, issuerPart.Asn1.pData, issuerPart.Asn1.usLen);
GMEM_Free(issuerPart.Asn1.pData);
pCurrent += issuerPart.Asn1.usLen;
memcpy(pCurrent, validityPart.Asn1.pData, validityPart.Asn1.usLen);
GMEM_Free(validityPart.Asn1.pData);
pCurrent += validityPart.Asn1.usLen;
memcpy(pCurrent, subjectPart.Asn1.pData, subjectPart.Asn1.usLen);
GMEM_Free(subjectPart.Asn1.pData);
pCurrent += subjectPart.Asn1.usLen;
memcpy(pCurrent, subjectPKInfoPart.Asn1.pData, subjectPKInfoPart.Asn1.usLen);
GMEM_Free(subjectPKInfoPart.Asn1.pData);
pCurrent += subjectPKInfoPart.Asn1.usLen;
if (bIssuerUIDPresent == TRUE)
{
memcpy(pCurrent, issuerUIDPart.Asn1.pData, issuerUIDPart.Asn1.usLen);
GMEM_Free(issuerUIDPart.Asn1.pData);
pCurrent += issuerUIDPart.Asn1.usLen;
}
if (bSubjectUIDPresent == TRUE)
{
memcpy(pCurrent, subjectUIDPart.Asn1.pData, subjectUIDPart.Asn1.usLen);
GMEM_Free(subjectUIDPart.Asn1.pData);
pCurrent += subjectUIDPart.Asn1.usLen;
}
if (bExtensionsPresent == TRUE)
{
memcpy(pCurrent, extensionsPart.Asn1.pData, extensionsPart.Asn1.usLen);
GMEM_Free(extensionsPart.Asn1.pData);
pCurrent += extensionsPart.Asn1.usLen;
}
return(RV_SUCCESS);
err:
GMEM_Free(serialNumberPart.Asn1.pData);
GMEM_Free(signaturePart.Asn1.pData);
GMEM_Free(issuerPart.Asn1.pData);
GMEM_Free(validityPart.Asn1.pData);
GMEM_Free(subjectPart.Asn1.pData);
GMEM_Free(subjectPKInfoPart.Asn1.pData);
GMEM_Free(issuerUIDPart.Asn1.pData);
GMEM_Free(subjectUIDPart.Asn1.pData);
GMEM_Free(extensionsPart.Asn1.pData);
return (rv);
}
/*******************************************************************************
* int CC_Decode_CertificateSerialNumber(BYTE *pInData,
* BLOC *pOutBloc,
* USHORT *pLength
* )
*
* Description : Décode une donnée de type CertificateSerialNumber.
* Ceci consiste seulement en le décodage brute (CC_RawDecode) de
* la donnée d'entrée.
*
* Remarks :
*
* In : pInBloc : la partie à décoder (champ Content)
*
* Out : pOutBloc : le décodé (mémoire allouée ici à libérer par la
* fonction appelante)
* pLength : la longueur de données encodés utilisée
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Decode_CertificateSerialNumber(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
)
{
int
rv;
rv = CC_RawDecode(pInData, pOutBloc, pLength, TRUE);
if (rv != RV_SUCCESS) return rv;
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_Decode_AlgorithmIdentifier(BYTE *pInData,
* BLOC *pOutBloc,
* USHORT *pLength
* )
*
* Description : Décode une donnée de type AlgorithmIdentifier.
* Ceci consiste en le décodage des différentes parties encodées
* successives, leurs enrobages respectifs (tags uniquement
* par la spec X.509), et la concaténation de ces résultats.
*
* Remarks : Voir l'encodage
*
* In : pInBloc : la partie à décoder (champ Content)
*
* Out : pOutBloc : le décodé (mémoire allouée ici à libérer par la
* fonction appelante)
* pLength : la longueur de données encodés utilisée
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Decode_AlgorithmIdentifier(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
)
{
ASN1
AlgorithmPart,
ParametersPart;
BOOL
bNullParam = FALSE,
bNoParam = FALSE;
int
rv;
USHORT
AlgoIndex,
Length;
AlgorithmPart.Asn1.pData = NULL;
ParametersPart.Asn1.pData = NULL;
if (pInData[0] == ESCAPE_CHAR)
{
rv = CC_RawDecode(&pInData[1], pOutBloc, &Length, TRUE);
*pLength = 1 + Length;
}
else
{
if (pInData[0] == ABSENT_PARAMETER_CHAR)
{
bNoParam = TRUE;
bNullParam = FALSE;
AlgoIndex = pInData[1];
}
else
{
bNoParam = ((pInData[0] & 0x80) != 0);
bNullParam = bNoParam;
AlgoIndex = pInData[0] & 0x7F;
}
if (bNoParam == TRUE)
{
AlgorithmPart.Content.usLen = (USHORT)strlen(AlgorithmTypeDict[AlgoIndex]);
if ((AlgorithmPart.Content.pData = GMEM_Alloc(AlgorithmPart.Content.usLen)) == NULL_PTR)
{
return (RV_MALLOC_FAILED);
}
memcpy(AlgorithmPart.Content.pData,
AlgorithmTypeDict[AlgoIndex],
AlgorithmPart.Content.usLen);
AlgorithmPart.Tag = TAG_OBJECT_IDENTIFIER;
rv = CC_BuildAsn1(&AlgorithmPart);
GMEM_Free(AlgorithmPart.Content.pData);
if (rv != RV_SUCCESS) goto err;
if (bNullParam == FALSE)
{
pOutBloc->usLen = AlgorithmPart.Asn1.usLen;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
memcpy(pOutBloc->pData, AlgorithmPart.Asn1.pData, AlgorithmPart.Asn1.usLen);
*pLength = 2;
GMEM_Free(AlgorithmPart.Asn1.pData);
}
else
{
pOutBloc->usLen = AlgorithmPart.Asn1.usLen + 2;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
memcpy(pOutBloc->pData, AlgorithmPart.Asn1.pData, AlgorithmPart.Asn1.usLen);
pOutBloc->pData[AlgorithmPart.Asn1.usLen] = 0x05;
pOutBloc->pData[AlgorithmPart.Asn1.usLen+1] = 0x00;
*pLength = 1;
GMEM_Free(AlgorithmPart.Asn1.pData);
}
}
else
{
AlgorithmPart.Content.usLen = (USHORT)strlen(AlgorithmTypeDict[AlgoIndex]);
if ((AlgorithmPart.Content.pData = GMEM_Alloc(AlgorithmPart.Content.usLen)) == NULL_PTR)
{
return (RV_MALLOC_FAILED);
}
memcpy(AlgorithmPart.Content.pData,
AlgorithmTypeDict[AlgoIndex],
AlgorithmPart.Content.usLen);
AlgorithmPart.Tag = TAG_OBJECT_IDENTIFIER;
rv = CC_BuildAsn1(&AlgorithmPart);
GMEM_Free(AlgorithmPart.Content.pData);
if (rv != RV_SUCCESS) goto err;
/* On recupère directement l'asn1 des paramètres */
rv = CC_RawDecode(&pInData[1], &(ParametersPart.Asn1), &Length, TRUE);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen = AlgorithmPart.Asn1.usLen + ParametersPart.Asn1.usLen;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
memcpy(pOutBloc->pData,
AlgorithmPart.Asn1.pData,
AlgorithmPart.Asn1.usLen);
memcpy(pOutBloc->pData + AlgorithmPart.Asn1.usLen,
ParametersPart.Asn1.pData,
ParametersPart.Asn1.usLen);
*pLength = 1 + Length;
GMEM_Free(AlgorithmPart.Asn1.pData);
GMEM_Free(ParametersPart.Asn1.pData);
}
}
return (RV_SUCCESS);
err:
GMEM_Free(AlgorithmPart.Asn1.pData);
GMEM_Free(ParametersPart.Asn1.pData);
return rv;
}
/*******************************************************************************
* int CC_Decode_Name(BYTE *pInData,
* BLOC *pOutBloc,
* USHORT *pLength
* )
*
* Description : Décode une donnée de type Name.
* Ceci consiste en le décodage des différentes parties encodées
* successives, leurs enrobages respectifs (tags uniquement
* par la spec X.509), et la concaténation de ces résultats.
*
* Remarks : Voir l'encodage
*
* In : pInBloc : la partie à décoder (champ Content)
*
* Out : pOutBloc : le décodé (mémoire allouée ici à libérer par la
* fonction appelante)
* pLength : la longueur de données encodés utilisée
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Decode_Name(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
)
{
ASN1
RDN[MAX_RDN];
BYTE
*pCurrent;
int
rv;
USHORT
i,
usNbRDN,
Length;
/* Décodage des différents composants et calcul de la longueur nécessaire */
pCurrent = pInData;
pOutBloc->usLen = 0;
usNbRDN = (USHORT) *pCurrent;
pCurrent++;
for (i = 0; i < usNbRDN; i++)
{
RDN[i].Asn1.pData = NULL;
}
for (i = 0; i < usNbRDN; i++)
{
rv = CC_Decode_RDN(pCurrent, &(RDN[i].Content), &Length);
if (rv != RV_SUCCESS) goto err;
RDN[i].Tag = TAG_SET_OF;
rv = CC_BuildAsn1(&RDN[i]);
GMEM_Free(RDN[i].Content.pData);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen += RDN[i].Asn1.usLen;
pCurrent += Length;
}
*pLength = (unsigned short)(DWORD) (pCurrent - pInData);
/* Reconstruction du Name décodé */
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
pCurrent = pOutBloc->pData;
for (i = 0; i < usNbRDN; i++)
{
memcpy(pCurrent, RDN[i].Asn1.pData, RDN[i].Asn1.usLen);
GMEM_Free(RDN[i].Asn1.pData);
pCurrent += RDN[i].Asn1.usLen;
}
return(RV_SUCCESS);
err:
for (i = 0; i < usNbRDN; i++)
{
GMEM_Free(RDN[i].Asn1.pData);
}
return rv;
}
/*******************************************************************************
* int CC_Decode_RDN(BYTE *pInData,
* BLOC *pOutBloc,
* USHORT *pLength
* )
*
* Description : Décode une donnée de type RelativeDistinguishedName.
* Ceci consiste en le décodage des différentes parties encodées
* successives, leurs enrobages respectifs (tags uniquement
* par la spec X.509), et la concaténation de ces résultats.
*
* Remarks : Voir l'encodage
*
* In : pInBloc : la partie à décoder (champ Content)
*
* Out : pOutBloc : le décodé (mémoire allouée ici à libérer par la
* fonction appelante)
* pLength : la longueur de données encodés utilisée
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Decode_RDN(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
)
{
ASN1
AVA[MAX_AVA];
BYTE
*pCurrent;
int
rv;
USHORT
i,
usNbAVA,
Length;
/* Décodage des différents composants et calcul de la longueur nécessaire */
pCurrent = pInData;
pOutBloc->usLen = 0;
usNbAVA = *pCurrent;
pCurrent++;
for (i = 0; i < usNbAVA; i++)
{
AVA[i].Asn1.pData = NULL;
}
for (i = 0; i < usNbAVA; i++)
{
rv = CC_Decode_AVA(pCurrent, &(AVA[i].Content), &Length);
if (rv != RV_SUCCESS) goto err;
AVA[i].Tag = TAG_SEQUENCE;
rv = CC_BuildAsn1(&AVA[i]);
GMEM_Free(AVA[i].Content.pData);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen += AVA[i].Asn1.usLen;
pCurrent += Length;
}
*pLength = (unsigned short)(DWORD) (pCurrent - pInData);
/* Reconstruction du Name décodé */
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
pCurrent = pOutBloc->pData;
for (i = 0; i < usNbAVA; i++)
{
memcpy(pCurrent, AVA[i].Asn1.pData, AVA[i].Asn1.usLen);
GMEM_Free(AVA[i].Asn1.pData);
pCurrent += AVA[i].Asn1.usLen;
}
return(RV_SUCCESS);
err:
for (i = 0; i < usNbAVA; i++)
{
GMEM_Free(AVA[i].Asn1.pData);
}
return rv;
}
/*******************************************************************************
* int CC_Decode_AVA(BYTE *pInData,
* BLOC *pOutBloc,
* USHORT *pLength
* )
*
* Description : Décode une donnée de type AttributeValueAssertion.
* Ceci consiste en le décodage des différentes parties encodées
* successives, leurs enrobages respectifs (tags uniquement
* par la spec X.509), et la concaténation de ces résultats.
*
* Remarks : Voir l'encodage
*
* In : pInBloc : la partie à décoder (champ Content)
*
* Out : pOutBloc : le décodé (mémoire allouée ici à libérer par la
* fonction appelante)
* pLength : la longueur de données encodés utilisée
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Decode_AVA(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
)
{
ASN1
AttributeTypePart,
AttributeValuePart;
BYTE
*pCurrent;
int
rv;
USHORT
AttributeTypeIndex,
Length;
AttributeTypePart.Asn1.pData = NULL;
AttributeValuePart.Asn1.pData = NULL;
if (pInData[0] == ESCAPE_CHAR)
{
pCurrent = &pInData[1];
rv = CC_RawDecode(pCurrent, &(AttributeTypePart.Content), &Length, TRUE);
if (rv != RV_SUCCESS) goto err;
AttributeTypePart.Tag = TAG_OBJECT_IDENTIFIER;
rv = CC_BuildAsn1(&AttributeTypePart);
GMEM_Free(AttributeTypePart.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
/* Ce que l'on décode contient déjà l'enrobage */
rv = CC_RawDecode(pCurrent, &(AttributeValuePart.Asn1), &Length, TRUE);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
*pLength = (unsigned short)(DWORD) (pCurrent - pInData);
pOutBloc->usLen = AttributeTypePart.Asn1.usLen
+ AttributeValuePart.Asn1.usLen;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
pCurrent = pOutBloc->pData;
memcpy(pCurrent, AttributeTypePart.Asn1.pData, AttributeTypePart.Asn1.usLen);
GMEM_Free(AttributeTypePart.Asn1.pData);
pCurrent += AttributeTypePart.Asn1.usLen;
memcpy(pCurrent, AttributeValuePart.Asn1.pData, AttributeValuePart.Asn1.usLen);
GMEM_Free(AttributeValuePart.Asn1.pData);
pCurrent += AttributeValuePart.Asn1.usLen;
}
else
{
AttributeTypeIndex = pInData[0];
AttributeTypePart.Content.usLen = (USHORT)strlen(AttributeTypeDict[AttributeTypeIndex]);
if ((AttributeTypePart.Content.pData = GMEM_Alloc(AttributeTypePart.Content.usLen))
== NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
memcpy(AttributeTypePart.Content.pData,
AttributeTypeDict[AttributeTypeIndex],
AttributeTypePart.Content.usLen);
AttributeTypePart.Tag = TAG_OBJECT_IDENTIFIER;
rv = CC_BuildAsn1(&AttributeTypePart);
GMEM_Free(AttributeTypePart.Content.pData);
if (rv != RV_SUCCESS) goto err;
rv = CC_RawDecode(&pInData[1], &(AttributeValuePart.Asn1), &Length, TRUE);
if (rv != RV_SUCCESS) goto err;
pOutBloc->usLen = AttributeTypePart.Asn1.usLen
+ AttributeValuePart.Asn1.usLen;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
pCurrent = pOutBloc->pData;
memcpy(pCurrent, AttributeTypePart.Asn1.pData, AttributeTypePart.Asn1.usLen);
GMEM_Free(AttributeTypePart.Asn1.pData);
pCurrent += AttributeTypePart.Asn1.usLen;
memcpy(pCurrent, AttributeValuePart.Asn1.pData, AttributeValuePart.Asn1.usLen);
GMEM_Free(AttributeValuePart.Asn1.pData);
pCurrent += AttributeValuePart.Asn1.usLen;
*pLength = 1 + Length;
}
return(RV_SUCCESS);
err:
GMEM_Free(AttributeTypePart.Asn1.pData);
GMEM_Free(AttributeValuePart.Asn1.pData);
return rv;
}
/*******************************************************************************
* int CC_Decode_Validity(BYTE *pInData,
* BLOC *pOutBloc,
* USHORT *pLength
* )
*
* Description : Décode une donnée de type Validity.
* Ceci consiste en le décodage des différentes parties encodées
* successives, leurs enrobages respectifs (tags uniquement
* par la spec X.509), et la concaténation de ces résultats.
*
* Remarks : Voir l'encodage
*
* In : pInBloc : la partie à décoder (champ Content)
*
* Out : pOutBloc : le décodé (mémoire allouée ici à libérer par la
* fonction appelante)
* pLength : la longueur de données encodés utilisée
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Decode_Validity(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
)
{
ASN1
notBeforePart,
notAfterPart;
BYTE
notBeforeFormat,
notAfterFormat,
*pCurrent;
int
rv;
USHORT
Length;
notBeforePart.Asn1.pData = NULL;
notAfterPart.Asn1.pData = NULL;
pCurrent = pInData;
notBeforeFormat = (*pCurrent & 0xF0) >> 4;
notAfterFormat = *pCurrent & 0x0F;
pCurrent++;
rv = CC_Decode_UTCTime(pCurrent, notBeforeFormat, &(notBeforePart.Content), &Length);
if (rv != RV_SUCCESS) goto err;
notBeforePart.Tag = TAG_UTCT;
rv = CC_BuildAsn1(&notBeforePart);
GMEM_Free(notBeforePart.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
rv = CC_Decode_UTCTime(pCurrent, notAfterFormat, &(notAfterPart.Content), &Length);
if (rv != RV_SUCCESS) goto err;
notAfterPart.Tag = TAG_UTCT;
rv = CC_BuildAsn1(&notAfterPart);
GMEM_Free(notAfterPart.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
*pLength = (unsigned short)(DWORD) (pCurrent - pInData);
/* Calcul de la longueur de Validity décodé et allocation */
pOutBloc->usLen = notBeforePart.Asn1.usLen
+ notAfterPart.Asn1.usLen;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
/* Reconstruction de Validity décodé */
pCurrent = pOutBloc->pData;
memcpy(pCurrent, notBeforePart.Asn1.pData, notBeforePart.Asn1.usLen);
GMEM_Free(notBeforePart.Asn1.pData);
pCurrent += notBeforePart.Asn1.usLen;
memcpy(pCurrent, notAfterPart.Asn1.pData, notAfterPart.Asn1.usLen);
GMEM_Free(notAfterPart.Asn1.pData);
pCurrent += notAfterPart.Asn1.usLen;
return(RV_SUCCESS);
err:
GMEM_Free(notBeforePart.Asn1.pData);
GMEM_Free(notAfterPart.Asn1.pData);
return rv;
}
/*******************************************************************************
* int CC_Decode_UTCTime(BYTE *pInData,
* BYTE Format,
* BLOC *pOutBloc,
* USHORT *pLength
* )
*
* Description : Décode une donnée de type UTCTime.
* Ceci consiste en la reconstruction de la chaine initiale suivant
* le format au quel elle était exprimée.
*
* Remarks : Voir l'encodage
*
* In : pInBloc : la partie à décoder (champ Content)
* Format : indique au quel format était la donnée d'entrée
*
* Out : pOutBloc : le décodé (mémoire allouée ici à libérer par la
* fonction appelante)
* pLength : la longueur de données encodés utilisée
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* RV_INVALID_DATA : Le format spécifié en entrée est invalide.
*
*******************************************************************************/
int CC_Decode_UTCTime(BYTE *pInData,
BYTE Format,
BLOC *pOutBloc,
USHORT *pLength
)
{
BOOL
bBissextile = FALSE;
BYTE
*pCurrent;
ULONG
ulTime,
ulNbHour,
ulNbMinute;
USHORT
usNbDeltaMinute,
usNbDay,
usNbFourYears,
usNbDayInYear,
usYear,
usMonth,
usDay,
usHour,
usMinute,
usSecond,
usDeltaHour,
usDeltaMinute;
ulTime = *(ULONG UNALIGNED *)pInData; //memcpy( &ulTime, (ULONG *) &pInData[0],4);
switch(Format)
{
case UTCT_YYMMDDhhmmssZ :
case UTCT_YYMMDDhhmmssphhmm :
case UTCT_YYMMDDhhmmssmhhmm :
usSecond = (USHORT) (ulTime % 60);
ulNbMinute = ulTime / 60;
break;
default :
ulNbMinute = ulTime;
break;
}
switch(Format)
{
case UTCT_YYMMDDhhmmphhmm :
case UTCT_YYMMDDhhmmmhhmm :
case UTCT_YYMMDDhhmmssphhmm :
case UTCT_YYMMDDhhmmssmhhmm :
*pLength = 6;
usNbDeltaMinute = *(USHORT UNALIGNED *)&pInData[4]; //memcpy(&usNbDeltaMinute, (USHORT *) &pInData[4], 2);
ASSERT((usNbDeltaMinute >= 0) && (usNbDeltaMinute < 3600));
usDeltaMinute = usNbDeltaMinute % 60;
usDeltaHour = usNbDeltaMinute / 60;
break;
default :
*pLength = 4;
break;
}
usMinute = (USHORT) (ulNbMinute % 60);
ulNbHour = ulNbMinute / 60;
usHour = (USHORT) (ulNbHour % 24);
usNbDay = (USHORT) (ulNbHour / 24);
usNbFourYears = usNbDay / 1461;
usNbDay = usNbDay % 1461;
usYear = 4 * usNbFourYears;
if ((usNbDay >= 0) && (usNbDay <= 365))
{
bBissextile = TRUE;
usNbDayInYear = usNbDay;
}
if ((usNbDay >= 366) && (usNbDay <= 730))
{
usYear += 1;
usNbDayInYear = usNbDay - 366;
}
if ((usNbDay >= 731) && (usNbDay <= 1095))
{
usYear += 2;
usNbDayInYear = usNbDay - 731;
}
if ((usNbDay >= 1096) && (usNbDay <= 1460))
{
usYear += 3;
usNbDayInYear = usNbDay - 1096;
}
usMonth = 1;
while (usNbDayInYear >= (((usMonth >= 2) && (bBissextile)) ?
NbDaysInMonth[usMonth] + 1 :
NbDaysInMonth[usMonth]))
{
usMonth++;
}
usDay = usNbDayInYear - (((usMonth - 1 >= 2) && (bBissextile)) ?
NbDaysInMonth[usMonth - 1] + 1 :
NbDaysInMonth[usMonth - 1])
+ 1;
switch(Format)
{
case UTCT_YYMMDDhhmmZ :
pOutBloc->usLen = 11;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
pCurrent = pOutBloc->pData;
*pCurrent++ = '0' + usYear / 10;
*pCurrent++ = '0' + usYear % 10;
*pCurrent++ = '0' + usMonth / 10;
*pCurrent++ = '0' + usMonth % 10;
*pCurrent++ = '0' + usDay / 10;
*pCurrent++ = '0' + usDay % 10;
*pCurrent++ = '0' + usHour / 10;
*pCurrent++ = '0' + usHour % 10;
*pCurrent++ = '0' + usMinute / 10;
*pCurrent++ = '0' + usMinute % 10;
*pCurrent = 'Z';
break;
case UTCT_YYMMDDhhmmphhmm :
pOutBloc->usLen = 15;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
pCurrent = pOutBloc->pData;
*pCurrent++ = '0' + usYear / 10;
*pCurrent++ = '0' + usYear % 10;
*pCurrent++ = '0' + usMonth / 10;
*pCurrent++ = '0' + usMonth % 10;
*pCurrent++ = '0' + usDay / 10;
*pCurrent++ = '0' + usDay % 10;
*pCurrent++ = '0' + usHour / 10;
*pCurrent++ = '0' + usHour % 10;
*pCurrent++ = '0' + usMinute / 10;
*pCurrent++ = '0' + usMinute % 10;
*pCurrent++ = '+';
*pCurrent++ = '0' + usDeltaHour / 10;
*pCurrent++ = '0' + usDeltaHour % 10;
*pCurrent++ = '0' + usDeltaMinute / 10;
*pCurrent++ = '0' + usDeltaMinute % 10;
break;
case UTCT_YYMMDDhhmmmhhmm :
pOutBloc->usLen = 15;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
pCurrent = pOutBloc->pData;
*pCurrent++ = '0' + usYear / 10;
*pCurrent++ = '0' + usYear % 10;
*pCurrent++ = '0' + usMonth / 10;
*pCurrent++ = '0' + usMonth % 10;
*pCurrent++ = '0' + usDay / 10;
*pCurrent++ = '0' + usDay % 10;
*pCurrent++ = '0' + usHour / 10;
*pCurrent++ = '0' + usHour % 10;
*pCurrent++ = '0' + usMinute / 10;
*pCurrent++ = '0' + usMinute % 10;
*pCurrent++ = '-';
*pCurrent++ = '0' + usDeltaHour / 10;
*pCurrent++ = '0' + usDeltaHour % 10;
*pCurrent++ = '0' + usDeltaMinute / 10;
*pCurrent++ = '0' + usDeltaMinute % 10;
break;
case UTCT_YYMMDDhhmmssZ :
pOutBloc->usLen = 13;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
pCurrent = pOutBloc->pData;
*pCurrent++ = '0' + usYear / 10;
*pCurrent++ = '0' + usYear % 10;
*pCurrent++ = '0' + usMonth / 10;
*pCurrent++ = '0' + usMonth % 10;
*pCurrent++ = '0' + usDay / 10;
*pCurrent++ = '0' + usDay % 10;
*pCurrent++ = '0' + usHour / 10;
*pCurrent++ = '0' + usHour % 10;
*pCurrent++ = '0' + usMinute / 10;
*pCurrent++ = '0' + usMinute % 10;
*pCurrent++ = '0' + usSecond / 10;
*pCurrent++ = '0' + usSecond % 10;
*pCurrent++ = 'Z';
break;
case UTCT_YYMMDDhhmmssphhmm :
pOutBloc->usLen = 17;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
pCurrent = pOutBloc->pData;
*pCurrent++ = '0' + usYear / 10;
*pCurrent++ = '0' + usYear % 10;
*pCurrent++ = '0' + usMonth / 10;
*pCurrent++ = '0' + usMonth % 10;
*pCurrent++ = '0' + usDay / 10;
*pCurrent++ = '0' + usDay % 10;
*pCurrent++ = '0' + usHour / 10;
*pCurrent++ = '0' + usHour % 10;
*pCurrent++ = '0' + usMinute / 10;
*pCurrent++ = '0' + usMinute % 10;
*pCurrent++ = '0' + usSecond / 10;
*pCurrent++ = '0' + usSecond % 10;
*pCurrent++ = '+';
*pCurrent++ = '0' + usDeltaHour / 10;
*pCurrent++ = '0' + usDeltaHour % 10;
*pCurrent++ = '0' + usDeltaMinute / 10;
*pCurrent++ = '0' + usDeltaMinute % 10;
break;
case UTCT_YYMMDDhhmmssmhhmm :
pOutBloc->usLen = 17;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
pCurrent = pOutBloc->pData;
*pCurrent++ = '0' + usYear / 10;
*pCurrent++ = '0' + usYear % 10;
*pCurrent++ = '0' + usMonth / 10;
*pCurrent++ = '0' + usMonth % 10;
*pCurrent++ = '0' + usDay / 10;
*pCurrent++ = '0' + usDay % 10;
*pCurrent++ = '0' + usHour / 10;
*pCurrent++ = '0' + usHour % 10;
*pCurrent++ = '0' + usMinute / 10;
*pCurrent++ = '0' + usMinute % 10;
*pCurrent++ = '0' + usSecond / 10;
*pCurrent++ = '0' + usSecond % 10;
*pCurrent++ = '-';
*pCurrent++ = '0' + usDeltaHour / 10;
*pCurrent++ = '0' + usDeltaHour % 10;
*pCurrent++ = '0' + usDeltaMinute / 10;
*pCurrent++ = '0' + usDeltaMinute % 10;
break;
default :
return(RV_INVALID_DATA);
break;
}
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_Decode_SubjectPKInfo(BYTE *pInData,
* BLOC *pOutBloc,
* USHORT *pLength
* )
*
* Description : Décode une donnée de type SubjectPublicKeyInfo.
* Ceci consiste en le décodage des différentes parties encodées
* successives, leurs enrobages respectifs (tags uniquement
* par la spec X.509), et la concaténation de ces résultats.
*
* Remarks : Voir l'encodage
*
* In : pInBloc : la partie à décoder (champ Content)
*
* Out : pOutBloc : le décodé (mémoire allouée ici à libérer par la
* fonction appelante)
* pLength : la longueur de données encodés utilisée
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Decode_SubjectPKInfo(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
)
{
ASN1
algorithmPart,
subjectPKPart;
// BLOC
// CompData;
BYTE
*pCurrent;
int
rv;
USHORT
Length;
algorithmPart.Asn1.pData = NULL;
subjectPKPart.Asn1.pData = NULL;
pCurrent = pInData;
rv = CC_Decode_AlgorithmIdentifier(pCurrent, &(algorithmPart.Content), &Length);
if (rv != RV_SUCCESS) goto err;
algorithmPart.Tag = TAG_SEQUENCE;
rv = CC_BuildAsn1(&algorithmPart);
GMEM_Free(algorithmPart.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
#ifdef _TRICKY_COMPRESSION
/* Ne pas faire le RawDecode a permis de gagner l'octet 0xFF */
#ifdef _OPT_HEADER
if (pCurrent[0] < 0x80)
{
CompData.usLen = pCurrent[0];
CompData.pData = &(pCurrent[1]);
Length = CompData.usLen + 1;
}
else
{
CompData.usLen = ((pCurrent[0] & 0x7F) << 8) + pCurrent[1];
CompData.pData = &(pCurrent[2]);
Length = CompData.usLen + 2;
}
#else /* _OPT_HEADER */
CompData.usLen = (pCurrent[0] << 8) + pCurrent[1];
CompData.pData = &(pCurrent[2]);
Length = CompData.usLen + 2;
#endif
subjectPKPart.Content.usLen = CompData.usLen;
if ((subjectPKPart.Content.pData =
GMEM_Alloc(subjectPKPart.Content.usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
memcpy(subjectPKPart.Content.pData,
CompData.pData,
subjectPKPart.Content.usLen
);
subjectPKPart.Tag = TAG_BIT_STRING;
rv = CC_BuildAsn1(&subjectPKPart);
GMEM_Free(subjectPKPart.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
#else /* _TRICKY_COMPRESSION */
rv = CC_RawDecode(pCurrent, &(subjectPKPart.Content), &Length, FALSE);
if (rv != RV_SUCCESS) goto err;
subjectPKPart.Tag = TAG_BIT_STRING;
rv = CC_BuildAsn1(&subjectPKPart);
GMEM_Free(subjectPKPart.Content.pData);
if (rv != RV_SUCCESS) goto err;
pCurrent += Length;
#endif
*pLength = (unsigned short)(DWORD) (pCurrent - pInData);
/* Calcul de la longueur du décodé et allocation */
pOutBloc->usLen = algorithmPart.Asn1.usLen
+ subjectPKPart.Asn1.usLen;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
/* Reconstruction */
pCurrent = pOutBloc->pData;
memcpy(pCurrent, algorithmPart.Asn1.pData, algorithmPart.Asn1.usLen);
GMEM_Free(algorithmPart.Asn1.pData);
pCurrent += algorithmPart.Asn1.usLen;
memcpy(pCurrent, subjectPKPart.Asn1.pData, subjectPKPart.Asn1.usLen);
GMEM_Free(subjectPKPart.Asn1.pData);
pCurrent += subjectPKPart.Asn1.usLen;
return(RV_SUCCESS);
err:
GMEM_Free(algorithmPart.Asn1.pData);
GMEM_Free(subjectPKPart.Asn1.pData);
return rv;
}
/*******************************************************************************
* int CC_Decode_UniqueIdentifier(BYTE *pInData,
* BLOC *pOutBloc,
* USHORT *pLength
* )
*
* Description : Décode une donnée de type UniqueIdentifier.
* Ceci consiste seulement en le décodage brute (CC_RawDecode) de
* la donnée d'entrée.
*
* Remarks :
*
* In : pInBloc : la partie à décoder (champ Content)
*
* Out : pOutBloc : le décodé (mémoire allouée ici à libérer par la
* fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Decode_UniqueIdentifier(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
)
{
int
rv;
rv = CC_RawDecode(pInData, pOutBloc, pLength, TRUE);
if (rv != RV_SUCCESS) return rv;
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_Decode_Extensions(BYTE *pInData,
* BLOC *pOutBloc,
* USHORT *pLength
* )
*
* Description : Décode une donnée de type Extensions.
* Ceci consiste en le décodage des différentes parties encodées
* successives, leurs enrobages respectifs (tags uniquement
* par la spec X.509), et la concaténation de ces résultats.
*
* Remarks : Voir l'encodage
* L'ajout d'un enrobage 'context spécifique' est requis
*
* In : pInBloc : la partie à décoder (champ Content)
*
* Out : pOutBloc : le décodé (mémoire allouée ici à libérer par la
* fonction appelante)
* pLength : la longueur de données encodés utilisée
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Decode_Extensions(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
)
{
ASN1
ExtensionPart[MAX_AVA],
InOutAsn1;
BYTE
*pCurrent;
int
rv;
USHORT
i,
usNbExtension,
Length;
/* Décodage des différents composants et calcul de la longueur nécessaire */
pCurrent = pInData;
InOutAsn1.Content.usLen = 0;
usNbExtension = *pCurrent;
pCurrent++;
for (i = 0; i < usNbExtension; i++)
{
ExtensionPart[i].Asn1.pData = NULL;
}
for (i = 0; i < usNbExtension; i++)
{
rv = CC_Decode_Extension(pCurrent, &(ExtensionPart[i].Content), &Length);
if (rv != RV_SUCCESS) goto err;
ExtensionPart[i].Tag = TAG_SEQUENCE;
rv = CC_BuildAsn1(&ExtensionPart[i]);
GMEM_Free(ExtensionPart[i].Content.pData);
if (rv != RV_SUCCESS) goto err;
InOutAsn1.Content.usLen += ExtensionPart[i].Asn1.usLen;
pCurrent += Length;
}
*pLength = (unsigned short)(DWORD) (pCurrent - pInData);
/* Reconstruction de la partie intérieure au 'context specific' */
if ((InOutAsn1.Content.pData = GMEM_Alloc(InOutAsn1.Content.usLen)) == NULL_PTR)
{
rv = RV_MALLOC_FAILED;
goto err;
}
pCurrent = InOutAsn1.Content.pData;
for (i = 0; i < usNbExtension; i++)
{
memcpy(pCurrent, ExtensionPart[i].Asn1.pData, ExtensionPart[i].Asn1.usLen);
GMEM_Free(ExtensionPart[i].Asn1.pData);
pCurrent += ExtensionPart[i].Asn1.usLen;
}
/* Ajout de l'enrobage 'context specific' */
InOutAsn1.Tag = TAG_SEQUENCE;
rv = CC_BuildAsn1(&InOutAsn1);
GMEM_Free(InOutAsn1.Content.pData);
if (rv != RV_SUCCESS) return rv;
*pOutBloc = InOutAsn1.Asn1;
return(RV_SUCCESS);
err:
for (i = 0; i < usNbExtension; i++)
{
GMEM_Free(ExtensionPart[i].Asn1.pData);
}
return rv;
}
/*******************************************************************************
* int CC_Decode_Extension(BYTE *pInData,
* BLOC *pOutBloc,
* USHORT *pLength
* )
*
* Description : Décode une donnée de type Extension.
* Ceci consiste seulement en le décodage brute (CC_RawDecode) de
* la donnée d'entrée.
*
* Remarks :
*
* In : pInBloc : la partie à décoder (champ Content)
*
* Out : pOutBloc : le décodé (mémoire allouée ici à libérer par la
* fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Decode_Extension(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
)
{
int
rv;
rv = CC_RawDecode(pInData, pOutBloc, pLength, TRUE);
if (rv != RV_SUCCESS) return rv;
return(RV_SUCCESS);
}
/*******************************************************************************
* int CC_Decode_Signature(BYTE *pInData,
* BLOC *pOutBloc,
* USHORT *pLength
* )
*
* Description : Décode la signature du certificat.
* Ceci consiste seulement en le décodage brute (CC_RawDecode) de
* la donnée d'entrée.
*
* Remarks : Voir l'encodage
*
* In : pInBloc : la partie à décoder (champ Content)
*
* Out : pOutBloc : le décodé (mémoire allouée ici à libérer par la
* fonction appelante)
*
* Responses : RV_SUCCESS : All is OK.
* RV_MALLOC_FAILED : Un malloc a échoué.
* Autre : D'autres codes d'erreur peuvent être retournés par des
* fonctions d'un niveau inférieur.
*
*******************************************************************************/
int CC_Decode_Signature(BYTE *pInData,
BLOC *pOutBloc,
USHORT *pLength
)
{
// BLOC
// CompData;
int
rv;
#ifdef _TRICKY_COMPRESSION
/* Ne pas faire le RawDecode a permis de gagner l'octet 0xFF */
#ifdef _OPT_HEADER
if (pInData[0] < 0x80)
{
CompData.usLen = pInData[0];
CompData.pData = &(pInData[1]);
*pLength = CompData.usLen + 1;
}
else
{
CompData.usLen = ((pInData[0] & 0x7F) << 8) + pInData[1];
CompData.pData = &(pInData[2]);
*pLength = CompData.usLen + 2;
}
#else /* _OPT_HEADER */
CompData.usLen = (pInData[0] << 8) + pInData[1];
CompData.pData = &(pInData[2]);
*pLength = CompData.usLen + 2;
#endif
pOutBloc->usLen = CompData.usLen;
if ((pOutBloc->pData = GMEM_Alloc(pOutBloc->usLen)) == NULL_PTR)
{
return(RV_MALLOC_FAILED);
}
memcpy(pOutBloc->pData, CompData.pData, pOutBloc->usLen);
#else /* _TRICKY_COMPRESSION */
rv = CC_RawDecode(pInData, pOutBloc, pLength, TRUE);
if (rv != RV_SUCCESS) return rv;
#endif
return(RV_SUCCESS);
}