pike.git / lib / modules / Standards.pmod / X509.pmod

version» Context lines:

pike.git/lib/modules/Standards.pmod/X509.pmod:33:   constant CERT_ROOT_UNTRUSTED = 5;      //!   constant CERT_BAD_SIGNATURE = 6;      #if 0   // A CA certificate does not have the CA basic constraint.   constant CERT_UNAUTHORIZED_CA = 7;   #endif    + protected enum keyUsage { +  digitalSignature = (1<<0), +  nonRepudiation = (1<<1), +  keyCertSign = (1<<5), +  cRLSign = (1<<6), + }; +  +    //! Unique identifier for the certificate issuer.   //!   //! X.509v2 (deprecated).   class IssuerId {    inherit BitString;    constant cls = 2;    constant tag = 1;   }      //! Unique identifier for the certificate subject.
pike.git/lib/modules/Standards.pmod/X509.pmod:887:   {    Sequence algorithm_id = c->pkcs_signature_algorithm_id(h);    if(!algorithm_id) error("Can't use %O for %O.\n", h, c);    if(serial<0) error("Serial number needs to be >=0.\n");    return sign_tbs(make_tbs(issuer, algorithm_id,    subject, c->pkcs_public_key(),    Integer(serial), ttl, extensions),    c, h)->get_der();   }    + //! Creates a certificate extension with the @[id] as identifier and + //! @[ext] as the extension payload. If the @[critical] flag is set + //! the extension will be marked as critical. + Sequence make_extension(Identifier id, Object ext, void|int critical) + { +  array seq = ({ id }); +  if( critical ) +  seq += ({ Boolean(1) }); +  return Sequence( seq+({ OctetString(ext->get_der()) }) ); + } +    //! Creates a selfsigned certificate, i.e. where issuer and subject   //! are the same entity. This entity is derived from the list of pairs   //! in @[name], which is encoded into an distinguished_name by   //! @[Standards.PKCS.Certificate.build_distinguished_name].   //!   //! @param c   //! The public key cipher used for the certificate, @[Crypto.RSA],   //! @[Crypto.DSA] or @[Crypto.ECC.Curve.ECDSA]. The object should be   //! initialized with both public and private keys.   //!   //! @param ttl   //! The validity of the certificate, in seconds, starting from   //! creation date.   //!   //! @param name   //! List of properties to create distinguished name from.   //!   //! @param extensions - //! List of extensions as ASN.1 structures. + //! List of extensions as ASN.1 structures. The extensions + //! subjectKeyIdentifier, keyUsage (flagged critical) and + //! basicConstraints (flagged critical) will automatically be added.   //!   //! @param h   //! The hash function to use for the certificate. Must be one of the   //! standardized PKCS hashes to be used with the given Crypto. By   //! default @[Crypto.SHA256] is selected for both RSA and DSA.   //!   //! @param serial   //! Serial number of the certificate. Defaults to generating a UUID   //! version1 value with random node. Some browsers will refuse   //! different certificates from the same signer with the same serial
pike.git/lib/modules/Standards.pmod/X509.pmod:927:   //!   //! @seealso   //! @[sign_key()], @[sign_tbs()]   string make_selfsigned_certificate(Crypto.Sign c, int ttl,    mapping|array name, array|void extensions,    void|Crypto.Hash h, void|int serial)   {    if(!serial)    serial = (int)Gmp.mpz(Standards.UUID.make_version1(-1)->encode(), 256);    Sequence dn = Certificate.build_distinguished_name(name); +  +  // Extensions mandated for Suite B Self-Signed CA Certificates, RFC +  // 5759 4.5.1. + #define ADD(X,Y,Z) extensions+=({ make_extension(Identifiers.ce_ids->X,Y,Z) }) +  +  if(!extensions) extensions = ({}); +  +  // While RFC 3280 section 4.2.1.2 suggest to only hash the BIT +  // STRING part of the subjectPublicKey, it is only a suggestion. +  ADD(subjectKeyIdentifier, +  OctetString( Crypto.SHA1.hash(c->pkcs_public_key()->get_der()) ), +  0); +  ADD(keyUsage, +  BitString()-> +  set_from_ascii(sprintf("%09b", keyCertSign|cRLSign|digitalSignature)), +  1); +  ADD(basicConstraints, +  Sequence(({Boolean(1)})), +  1); +  + #undef ADD +     return sign_key(dn, c, h||Crypto.SHA256, dn, serial, ttl, extensions);   }      //! Decodes a certificate and verifies that it is structually sound.   //! Returns a @[TBSCertificate] object if ok, otherwise @expr{0@}.   TBSCertificate decode_certificate(string|object cert)   {    if (stringp (cert)) {    cert = Standards.ASN1.Decode.simple_der_decode(cert, x509_types);    }
pike.git/lib/modules/Standards.pmod/X509.pmod:1007:   }         //! Verifies that all extensions mandated for certificate signing   //! certificates are present and valid.   TBSCertificate verify_root_certificate(TBSCertificate tbs)   {    if(!tbs) return 0;       multiset crit = tbs->critical + (<>); +  int self_signed = (tbs->issuer->get_der() == tbs->subject->get_der());    -  Object lookup(int num) +  Object lookup(string id)    { -  string id = Identifiers.ce_id->append(num)->get_der(); +  id = Identifiers.ce_ids[id]->get_der();    crit[id]=0;    return tbs->extensions[id];    };       // FIXME: Move extension parsing into tbs.       // id-ce-basicConstraints is required for certificates with public    // key used to validate certificate signatures. RFC 3280, 4.2.1.10. -  Object c = lookup(19); +  Object c = lookup("basicConstraints");    if( !c || c->type_name!="SEQUENCE" || sizeof(c)<1 || sizeof(c)>2 ||    c[0]->type_name!="BOOLEAN" ||    !c[0]->value )    {    DBG("verify root: Bad or missing id-ce-basicConstraints.\n");    return 0;    } -  // FIXME: Verify pathLenConstraint +  Sequence s = [object(Sequence)]c; +  if( sizeof(s)==2 && ( s[1]->type_name!="INTEGER" || 0 > s[1]->value ) ) +  { +  // FIXME: Compare with actual path length and not 0. +  DBG("verify root: Path length longer than pathLenConstraint.\n"); +  return 0; +  }       // id-ce-authorityKeyIdentifier is required, unless self signed. RFC    // 3280 4.2.1.1 -  if( !lookup(35) && tbs->issuer->get_der() != tbs->subject->get_der() ) +  if( !lookup("authorityKeyIdentifier") && !self_signed )    {    DBG("verify root: Missing id-ce-authorityKeyIdentifier.\n");    return 0;    }       // id-ce-subjectKeyIdentifier is required. RFC 3280 4.2.1.2 -  if( !lookup(14) ) +  if( !lookup("subjectKeyIdentifier") )    {    DBG("verify root: Missing id-ce-subjectKeyIdentifier.\n");    return 0;    }       // id-ce-keyUsage is required. RFC 3280 4.2.1.3 -  c = lookup(15); -  if( !c ) // FIXME: Look at usage bits +  c = lookup("keyUsage"); +  if( !c || c->type_name!="BIT STRING" )    {    DBG("verify root: Missing id-ce-keyUsage.\n");    return 0;    } -  +  keyUsage usage = (int)c; +  if( !( usage & digitalSignature ) ) +  { +  DBG("verify root: id-ce-keyUsage doesn't allow digitalSignature.\n"); +  return 0; +  } +  if( !( usage & keyCertSign ) ) // RFC 5759 +  { +  return 0; +  }    -  +     // One or more critical extensions have not been processed.    if( sizeof(crit) )    {    DBG("verify root: Critical unknown extensions %O.\n", crit);    return 0;    }       return tbs;   }