diff --git a/ctaocrypt/src/asn.c b/ctaocrypt/src/asn.c index e9709d02d..1f2b7312e 100644 --- a/ctaocrypt/src/asn.c +++ b/ctaocrypt/src/asn.c @@ -2106,6 +2106,14 @@ void CTaoCryptErrorString(int error, char* buffer) XSTRNCPY(buffer, "Setting Cert Issuer name error", max); break; + case CA_TRUE_E : + XSTRNCPY(buffer, "Setting basic constraint CA true error", max); + break; + + case EXTENSIONS_E : + XSTRNCPY(buffer, "Setting extensions error", max); + break; + case ASN_PARSE_E : XSTRNCPY(buffer, "ASN parsing error, invalid input", max); break; @@ -2401,6 +2409,7 @@ void InitCert(Cert* cert) cert->sigType = MD5wRSA; cert->daysValid = 500; cert->selfSigned = 1; + cert->isCA = 0; cert->bodySz = 0; cert->keyType = RSA_KEY; XMEMSET(cert->serial, 0, CTC_SERIAL_SIZE); @@ -2435,6 +2444,8 @@ typedef struct DerCert { byte subject[ASN_NAME_MAX]; /* subject encoded */ byte validity[MAX_DATE_SIZE*2 + MAX_SEQ_SZ*2]; /* before and after dates */ byte publicKey[MAX_PUBLIC_KEY_SZ]; /* rsa / ntru public key encoded */ + byte ca[MAX_CA_SZ]; /* basic constraint CA true size */ + byte extensions[MAX_EXTENSIONS_SZ]; /* all extensions */ int sizeSz; /* encoded size length */ int versionSz; /* encoded version length */ int serialSz; /* encoded serial length */ @@ -2443,6 +2454,8 @@ typedef struct DerCert { int subjectSz; /* encoded subject length */ int validitySz; /* encoded validity length */ int publicKeySz; /* encoded public key length */ + int caSz; /* encoded CA extension length */ + int extensionsSz; /* encoded extensions total length */ int total; /* total encoded lengths */ } DerCert; @@ -2717,6 +2730,41 @@ static byte GetNameId(int idx) } +/* encode all extensions, return total bytes written */ +static int SetExtensions(byte* output, const byte* ca, int caSz) +{ + byte sequence[MAX_SEQ_SZ]; + byte len[MAX_LENGTH_SZ]; + + int sz = 0; + int seqSz = SetSequence(caSz, sequence); + int lenSz = SetLength(seqSz + caSz, len); + + output[0] = 0xa3; /* extensions id */ + sz++; + memcpy(&output[sz], len, lenSz); /* length */ + sz += lenSz; + memcpy(&output[sz], sequence, seqSz); /* sequence */ + sz += seqSz; + memcpy(&output[sz], ca, caSz); /* ca */ + sz += caSz; + + return sz; +} + + +/* encode CA basic constraint true, return total bytes written */ +static int SetCa(byte* output) +{ + static const byte ca[] = { 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff }; + + memcpy(output, ca, sizeof(ca)); + + return (int)sizeof(ca); +} + + /* encode CertName into output, return total bytes written */ static int SetName(byte* output, CertName* name) { @@ -2888,8 +2936,27 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, RNG* rng, if (der->issuerSz == 0) return ISSUER_E; + /* CA */ + if (cert->isCA) { + der->caSz = SetCa(der->ca); + if (der->caSz == 0) + return CA_TRUE_E; + } + else + der->caSz = 0; + + /* extensions, just CA now */ + if (cert->isCA) { + der->extensionsSz = SetExtensions(der->extensions, der->ca, der->caSz); + if (der->extensionsSz == 0) + return EXTENSIONS_E; + } + else + der->extensionsSz = 0; + der->total = der->versionSz + der->serialSz + der->sigAlgoSz + - der->publicKeySz + der->validitySz + der->subjectSz + der->issuerSz; + der->publicKeySz + der->validitySz + der->subjectSz + der->issuerSz + + der->extensionsSz; return 0; } @@ -2923,6 +2990,11 @@ static int WriteCertBody(DerCert* der, byte* buffer) /* public key */ XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz); idx += der->publicKeySz; + if (der->extensionsSz) { + /* extensions */ + XMEMCPY(buffer + idx, der->extensions, der->extensionsSz); + idx += der->extensionsSz; + } return idx; } diff --git a/ctaocrypt/test/test.c b/ctaocrypt/test/test.c index 972b41cac..252abd296 100644 --- a/ctaocrypt/test/test.c +++ b/ctaocrypt/test/test.c @@ -1220,6 +1220,7 @@ int rsa_test() strncpy(myCert.subject.unit, "Development", CTC_NAME_SIZE); strncpy(myCert.subject.commonName, "www.yassl.com", CTC_NAME_SIZE); strncpy(myCert.subject.email, "info@yassl.com", CTC_NAME_SIZE); + myCert.isCA = 1; certSz = MakeSelfCert(&myCert, derCert, sizeof(derCert), &key, &rng); if (certSz < 0) diff --git a/cyassl/ctaocrypt/asn.h b/cyassl/ctaocrypt/asn.h index e1eb92add..bd49fc5c8 100644 --- a/cyassl/ctaocrypt/asn.h +++ b/cyassl/ctaocrypt/asn.h @@ -115,10 +115,13 @@ enum Misc_ASN { MAX_RSA_INT_SZ = 517, /* RSA raw sz 4096 for bits + tag + len(4) */ MAX_NTRU_KEY_SZ = 610, /* NTRU 112 bit public key */ MAX_NTRU_ENC_SZ = 628, /* NTRU 112 bit DER public encoding */ + MAX_LENGTH_SZ = 4, /* Max length size for DER encoding */ MAX_RSA_E_SZ = 16, /* Max RSA public e size */ - MAX_PUBLIC_KEY_SZ = MAX_NTRU_ENC_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2, + MAX_CA_SZ = 32, /* Max encoded CA basic constraint length */ + MAX_EXTENSIONS_SZ = 1 + MAX_LENGTH_SZ + MAX_CA_SZ, + /* Max total extensions, id + len + others */ + MAX_PUBLIC_KEY_SZ = MAX_NTRU_ENC_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2 /* use bigger NTRU size */ - MAX_LENGTH_SZ = 4 }; diff --git a/cyassl/ctaocrypt/asn_public.h b/cyassl/ctaocrypt/asn_public.h index d0ee9cf47..76372f958 100644 --- a/cyassl/ctaocrypt/asn_public.h +++ b/cyassl/ctaocrypt/asn_public.h @@ -69,6 +69,7 @@ typedef struct Cert { int daysValid; /* validity days */ int selfSigned; /* self signed flag */ CertName subject; /* subject info */ + int isCA; /* is this going to be a CA */ /* internal use only */ int bodySz; /* pre sign total size */ int keyType; /* public key type of subject */ @@ -85,6 +86,7 @@ typedef struct Cert { daysValid = 500 selfSigned = 1 (true) use subject as issuer subject = blank + isCA = 0 (false) keyType = RSA_KEY (default) */ CYASSL_API void InitCert(Cert*); diff --git a/cyassl/ctaocrypt/error.h b/cyassl/ctaocrypt/error.h index 8915e6fa2..1e58b3660 100644 --- a/cyassl/ctaocrypt/error.h +++ b/cyassl/ctaocrypt/error.h @@ -65,6 +65,8 @@ enum { DATE_E = -135, /* setting date validity error */ SUBJECT_E = -136, /* setting subject name error */ ISSUER_E = -137, /* setting issuer name error */ + CA_TRUE_E = -138, /* setting CA basic constraint true error */ + EXTENSIONS_E = -139, /* setting extensions error */ ASN_PARSE_E = -140, /* ASN parsing error, invalid input */ ASN_VERSION_E = -141, /* ASN version error, invalid number */