pike.git / lib / modules / Standards.pmod / PKCS.pmod / CSR.pmod

version» Context lines:

pike.git/lib/modules/Standards.pmod/PKCS.pmod/CSR.pmod:1: - //! Handling of Certifikate Signing Requests (PKCS-10) + //! Handling of Certificate Signing Requests (PKCS-10, @rfc{2314@}, + //! @rfc{2986@})      #pike __REAL_VERSION__   // #pragma strict_types -  + #require constant(Crypto.RSA)    - #if constant(Crypto.RSA) -  +    import Standards.ASN1.Types;    - class CSR_Attributes + // NOTE: RFC 2314 6.1 says that the tag is IMPLICIT, and + // RFC 2986 4.1 says that the tag is EXPLICIT! + // + // OpenSSL seems to use IMPLICIT tagging, + // so this is probably correct. + //! + class CRIAttributes   {    inherit .Certificate.Attributes; -  constant cls = 2; -  constant tag = 0; +  int(0..3) cls = 2; +  int(1..) tag = 0;   }    -  + // FIXME: Mark as deprecated! + constant CSR_Attributes = CRIAttributes; +  + //! CertificationRequestInfo   //! - Sequence build_csr(Crypto.RSA rsa, object name, -  mapping(string:array(object)) attributes) + //! This is the data that is signed by @[sign_cri()]. + class CRI   { -  Sequence info = Sequence( ({ Integer(0), name, -  .RSA.build_public_key(rsa), -  CSR_Attributes(.Identifiers.attribute_ids, -  attributes) }) ); -  return Sequence( ({ info, -  Sequence( -  ({ .Identifiers.rsa_md5_id, Null() }) ), -  BitString(rsa->pkcs_sign(info->get_der(), -  Crypto.MD5)) }) ); +  inherit Sequence; +  +  //! +  void `version=(int v) +  { +  der = UNDEFINED; +  if (v != 1) { +  error("Only version 1 is supported.\n");    } -  +  elements[0] = Integer(v-1); +  } +  int `version() +  { +  return elements[0]->value + 1; +  }    - #if 0 - object build_csr_dsa(Crypto.DSA dsa, object name) +  //! Certificate subject. +  void `subject=(Sequence i)    { -  Sequence info = Sequence( ({ Integer }) ); +  der = UNDEFINED; +  elements[1] = i;    } - #endif +  Sequence `subject() +  { +  return elements[1]; +  }    - #else - constant this_program_does_not_exist=1; - #endif +  //! Public key information. +  void `keyinfo=(Sequence ki) +  { +  der = UNDEFINED; +  elements[2] = ki; +  } +  Sequence `keyinfo() +  { +  return elements[2]; +  } +  +  //! Subject attributes. +  void `attributes=(Set|CRIAttributes attrs) +  { +  der = UNDEFINED; +  if ((attrs->type_name != "SET") && +  (attrs->type_name != "CONSTRUCTED")) { +  error("Invalid attributes: %O.\n", attrs->type_name); +  } +  if ((attrs->get_cls() != 2) || attrs->get_tag() || attrs->raw) { +  attrs = CRIAttributes(attrs->elements); +  } +  elements[3] = attrs; +  } +  CRIAttributes `attributes() +  { +  return elements[3]; +  } +  +  protected void create(Sequence|void asn1) +  { +  if (asn1) { +  if ((asn1->type_name != "SEQUENCE") || +  (sizeof(asn1->elements) != 4) || +  (asn1[0]->type_name != "INTEGER") || +  asn1[0]->value) { +  error("Invalid CRI."); +  } +  elements = asn1->elements; +  attributes = elements[3]; +  } else { +  elements = ({ +  Integer(0), // version (v1) +  Null, // subject +  Null, // subjectPKInfo +  CRIAttributes(({})), // attributes +  }); +  } +  } + } +  + //! Sign a @[CRI] to generate a Certificate Signing Request. + //! + //! @param cri + //! CertificationRequestInfo to sign. + //! + //! @param sign + //! Signature to use. Must have a private key set that matches + //! the public key in the keyinfo in @[cri]. + //! + //! @param hash + //! Hash algorithm to use for the signature. + Sequence sign_cri(CRI cri, Crypto.Sign sign, Crypto.Hash hash) + { +  return Standards.PKCS.Signature.sign(cri, sign, hash); + } +  + //! Build a Certificate Signing Request. + //! + //! @param sign + //! Signature algorithm for the certificate. Both private and + //! public keys must be set. + //! + //! @param name + //! The distinguished name for the certificate. + //! + //! @param attributes + //! Attributes from PKCS #9 to add to the certificate. + //! + //! @param hash + //! Hash algoritm to use for the CSR signature. + //! Defaults to @[Crypto.SHA256]. + //! + //! @note + //! Prior to Pike 8.0 this function only supported signing + //! with @[Crypto.RSA] and the default (and only) hash was + //! @[Crypto.MD5]. + Sequence build_csr(Crypto.Sign sign, Sequence name, +  mapping(string:array(Object)) attributes, +  Crypto.Hash|void hash) + { +  Sequence info = Sequence( ({ Integer(0), // v1 +  name, +  sign->pkcs_public_key(), +  CRIAttributes(.Identifiers.attribute_ids, +  attributes) }) ); +  hash = hash || Crypto.SHA256; +  return Sequence( ({ info, +  sign->pkcs_signature_algorithm_id(hash), +  BitString(sign->pkcs_sign(info->get_der(), hash)) +  }) ); + }