From: Nicolas Thill Date: Mon, 26 Mar 2007 02:51:55 +0000 (+0000) Subject: add sscep, a Simple SCEP (Simple Certificate Enrollment Protocol) client X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fsvn-archive%2Farchive.git;a=commitdiff_plain;h=07f1c614a46b099d789d5168c43b13a9b06909f0 add sscep, a Simple SCEP (Simple Certificate Enrollment Protocol) client SVN-Revision: 6701 --- diff --git a/net/sscep/Makefile b/net/sscep/Makefile new file mode 100644 index 0000000000..7c6bcdd2f2 --- /dev/null +++ b/net/sscep/Makefile @@ -0,0 +1,55 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +# $Id$ + +include $(TOPDIR)/rules.mk + +PKG_NAME:=sscep +PKG_VERSION:=20040325+ng2 +PKG_RELEASE:=1 + +PKG_SOURCE:=${PKG_NAME}.tgz +PKG_SOURCE_URL:=http://www.klake.org/~jt/sscep/ +PKG_MD5SUM:=b509cdf0de952841471e77499aa6e4ca +PKG_CAT:=zcat + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) +PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install + +include $(INCLUDE_DIR)/package.mk + +define Package/sscep + SECTION:=net + CATEGORY:=Network + DEPENDS:=+libopenssl + TITLE:=A Simple SCEP (Simple Certificate Enrollment Protocol) client + URL:=http://www.klake.org/~jt/sscep/ +endef + +define Build/Configure +endef + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) \ + $(TARGET_CONFIGURE_OPTS) \ + CFLAGS="$(TARGET_CFLAGS)" \ + CPPFLAGS="$(TARGET_CPPFLAGS)" \ + LDFLAGS="$(TARGET_LDFLAGS)" +endef + +define Package/sscep/conffiles +/etc/sscep.conf +endef + +define Package/sscep/install + $(INSTALL_DIR) $(1)/etc + $(INSTALL_CONF) $(PKG_BUILD_DIR)/sscep.conf $(1)/etc/ + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/sscep $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,sscep)) diff --git a/net/sscep/patches/001-certnanny.patch b/net/sscep/patches/001-certnanny.patch new file mode 100644 index 0000000000..6a373524db --- /dev/null +++ b/net/sscep/patches/001-certnanny.patch @@ -0,0 +1,3009 @@ +This patch adds support for signing requests with an existing key. +It was taken from CertNanny + +diff -uN sscep/Makefile sscep-ng2/Makefile +--- sscep/Makefile 2003-01-22 06:23:18.000000000 +0100 ++++ sscep-ng2/Makefile 2006-04-25 19:38:49.000000000 +0200 +@@ -7,13 +7,14 @@ + + CC = gcc + CFLAGS = -Wall -O ++LDLIBS = -lcrypto + + MAN = sscep.8 + PROG = sscep + OBJS = sscep.o init.o net.o sceputils.o pkcs7.o ias.o fileutils.o + + $(PROG): $(OBJS) +- $(CC) $(CFLAGS) -lcrypto -o $(PROG) $(OBJS) ++ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $(PROG) $(OBJS) $(LDLIBS) + + clean: + rm -f $(PROG) $(OBJS) $(MAN) core +diff -uN sscep/README sscep-ng2/README +--- sscep/README 2003-04-17 07:49:46.000000000 +0200 ++++ sscep-ng2/README 2006-04-28 10:27:44.000000000 +0200 +@@ -51,11 +51,13 @@ + o iPlanet CMS (getca and enroll works)* + o VeriSign Onsite (getca and enroll works)** + o Entrust VPN Connect (getca and enroll works)*** ++o OpenCA (getca, enroll, getcrl and automatic approval works)**** + + (*) by default, subjectAltName extensions are dropped from certificate + (**) only DNS subjectAltName allowed (demo mode) + (***) demo requires to use /C=US/O=Entrust +- ++(****) automatic approval according to newer SCEP drafts requires ++ OpenCA 0.9.2.4 or higher + + HOW TO COMPILE + ============== +@@ -76,7 +78,7 @@ + + $ ./sscep + +-sscep version 20030131 ++sscep version 2005XXXX + + Usage: ./sscep OPERATION [OPTIONS] + +@@ -103,6 +105,8 @@ + OPTIONS for OPERATION enroll are + -k Private key file + -r Certificate request file ++ -K Signature private key file ++ -O Signature certificate (used instead of self-signed) + -l Write enrolled certificate in file + -e Use different CA cert for encryption + -L Write selfsigned certificate in file +@@ -152,6 +156,16 @@ + CAIdentifier Some CAs require you to define this. Example: mydomain.com + Command line option: -i + ++CheckSubjectName ++ Check subject DN in the certificate return by the CA. The ++ default is to match on the public key only. Up to version ++ 20040325 sscep checked on the subject DN only, which is a ++ problem e.g. if the CA adds a SER attribute, enforces a ++ naming policy or fixes encoding errors (e.g. with Java keytool ++ and DC). ++ Example: yes ++ Command line option: -C ++ + CertReqFile Certificate request file created with mkrequest. + Example: ./local.csr + Command line option: -r +@@ -171,6 +185,21 @@ + the signature. Example: ./enc.crt + Command line option: -e + ++SignCertFile Instead of creating a self-signed certificate from the ++ new key pair use an already existing certficate/key to ++ sign the SCEP request. If the "old" certificate and ++ key is used, the CA can verify that the holder of the ++ private key for an existing certificate re-enrolls for ++ a renewal certificate, allowing for automatic approval ++ of the request. Requires specification of the corresponding ++ signature private key file (-K, SignKeyFile). ++ Example: ./sig.crt ++ Command line option: -O ++ ++SignKeyFile See SignCertFile. Specifies the corresponding private key. ++ Example: ./sig.key ++ Command line option: -K ++ + FingerPrint Display fingerprint algorithm. Available algorithms are md5 + and sha1. Default is md5. + Command line option: -F +@@ -367,6 +396,23 @@ + the challenge password), it returns SUCCESS as a first reply. Otherwise, the + enrollment requires manual signing and authentication (perhaps a phone call). + ++Newer SCEP draft versions allow to use the existing certificate (issued ++by the CA) to authenticate a renewal request. In this context, the SCEP ++request with the new public key is signed with the old certificate and ++key (instead of using a self-signed certificate created from the new ++key pair). ++To use this feature, use the command line options -O and -K to specify ++the old certificate and private key (SignCertFile and SignCertKey ++in the configuration file). ++The actual behaviour of the SCEP server depends on the CA policy and ++on the capabilities of the SCEP server (not all servers implement ++this feature, using the existing certificate with an older SCEP server ++may or may not work, depending on implementation). ++ ++Note: Newer versions of OpenCA (http://www.openca.info/) support ++an SCEP server that is capable of automatically approving SCEP requests ++signed with the already existing key pair. ++ + + STEP 5 - Use certificate + ======================== +diff -uN sscep/cmd.h sscep-ng2/cmd.h +--- sscep/cmd.h 2003-01-30 08:57:34.000000000 +0100 ++++ sscep-ng2/cmd.h 2006-04-28 10:01:10.000000000 +0200 +@@ -16,6 +16,9 @@ + int c_flag; + char *c_char; + ++/* Check subject DN */ ++int C_flag; ++ + /* Debug? */ + int d_flag; + +@@ -51,10 +54,18 @@ + char *k_char; + int k_flag; + ++/* Private key of already existing certificate */ ++char *K_char; ++int K_flag; ++ + /* Request count */ + int n_flag; + int n_num; + ++/* Already existing certificate (to be renewed) */ ++char *O_char; ++int O_flag; ++ + /* Proxy */ + char *p_char; + int p_flag; +diff -uN sscep/draft-nourse-scep-11.txt sscep-ng2/draft-nourse-scep-11.txt +--- sscep/draft-nourse-scep-11.txt 1970-01-01 01:00:00.000000000 +0100 ++++ sscep-ng2/draft-nourse-scep-11.txt 2006-04-25 16:27:03.000000000 +0200 +@@ -0,0 +1,2367 @@ ++ ++INTERNET DRAFT Xiaoyi Liu ++draft-nourse-scep-11.txt Cheryl Madson ++expires 11 Aug 2005 David McGrew ++(revised 11 Feb 2005) Andrew Nourse ++ Cisco Systems ++ ++Category: Informational 11 Feb 2005 ++ ++ ++Cisco Systems' Simple Certificate Enrollment Protocol(SCEP): ++ ++Status of this Memo ++ ++This document is an Internet-Draft and is NOT offered in accordance ++with Section 10 of RFC2026, and the author does not provide the IETF ++with any rights other than to publish as an Internet-Draft ++ ++Internet-Drafts are working documents of the Internet Engineering Task ++Force (IETF), its areas, and its working groups. Note that other ++groups may also distribute working documents as Internet-Drafts. ++ ++Internet-Drafts are draft documents valid for a maximum of six months ++and may be updated, replaced, or obsoleted by other documents at any ++time. It is inappropriate to use Internet- Drafts as reference ++material or to cite them other than as "work in progress." ++ ++The list of current Internet-Drafts can be accessed at ++http://www.ietf.org/ietf/1id-abstracts.txt ++ ++The list of Internet-Draft Shadow Directories can be accessed at ++http://www.ietf.org/shadow.html. ++ ++This memo provides information for the Internet community. This memo ++does not specify an Internet standard of any kind. Distribution of ++this memo is unlimited. ++ ++By submitting this Internet-Draft, I certify that any applicable patent ++or other IPR claims of which I am aware have been disclosed, or will be ++disclosed, and any of which I become aware will be disclosed, in accordance ++with RFC 3668. ++ ++Abstract ++ ++This document specifies the Simple Certificate Enrollment Protocol, ++a PKI communication protocol which leverages existing technology by ++using PKCS#7 and PKCS#10. SCEP is the evolution of the enrollment ++protocol developed by Verisign, Inc. for Cisco Systems, Inc. ++It now enjoys wide support in both client and CA implementations. ++ ++ ++Table of Contents ++ ++ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . 2 ++ 2. The Goal of SCEP . . . . . . . . . . . . . . . . . . . . . 3 ++ 2.1 SCEP Entity types . . . . . . . . . . . . . . . . . . . . 3 ++ 2.2 SCEP Operations Overview . . . . . . . . . . . . . . . . . 7 ++ 2.3 PKI Operation Transactional Behavior . . . . . . . . . . . 10 ++ 2.4 Security . . . . . . . . . . . . . . . . . . . . . . . . . 12 ++ 3. Transport Protocol . . . . . . . . . . . . . . . . . . . . 13 ++ 4. Secure Transportation: PKCS #7 . . . . . . . . . . . . . . 14 ++ 4.1 SCEP Message Format . . . . . . . . . . . . . . . . . . . 14 ++ ++ Liu/Madson/McGrew/Nourse [Page 2] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ 4.2 Signed Transaction Attributes . . . . . . . . . . . . . . 15 ++ 5. SCEP Transaction Specification . . . . . . . . . . . . . . 16 ++ 5.1 Certificate Enrollment . . . . . . . . . . . . . . . . . . 16 ++ 5.2 Poll for Requester Initial Certificate . . . . . . . . . . 22 ++ 5.3 Certificate Access . . . . . . . . . . . . . . . . . . . . 26 ++ 5.4 CRL Access . . . . . . . . . . . . . . . . . . . . . . . 27 ++ 5.5 Get Certificate Authority Certificate . . . . . . . . . . 31 ++ 5.6 Get Certificate Authority Certificate Chain . . . . . . . 33 ++ 6. Security Considerations . . . . . . . . . . . . . . . . . 33 ++ 7. Intellectual Propoerty . . . . . . . . . . . . . . . . . . 33 ++ 8. References . . . . . . . . . . . . . . . . . . . . . . . . 33 ++ Appendix A. Cisco Requester Subject Name Definition . . . . . . 34 ++ Appendix B. IPSEC Client Enrollment Certificate Request . . . . 35 ++ Appendix C. Private OID Definitions . . . . . . . . . . . . . 36 ++ Appendix D. Obtaining CRL by LDAP Query . . . . . . . . . . . . 36 ++ Appendix E. SCEP State Transitions . . . . . . . . . . . . . . 37 ++ Appendix F. CA Capabilities . . . . . . . . . . . . . . . . . . 40 ++ Appendix G. Certificate Renewal and CA Key Rollover . . . . . . 41 ++ Appendix H. PKIOperation via HTTP POST Message. . . . . . . . . 42 ++ Appendix Y. Author Contact Information. . . . . . . . . . . . . 43 ++ Appendix Z. Copyright Section . . . . . . . . . . . . . . . . . 43 ++ ++Section 1. Introduction ++ ++Public key technology is becoming more widely deployed and is becoming ++the basis for standards based security, such as the Internet Engineering ++Task Force's IPSEC and IKE protocols. With the use of public key ++certificates in network security protocols comes the need for a ++certificate management protocol that Public Key Infrastructure (PKI) ++clients and Certificate Authority servers can use to support certificate ++life cycle operations such as certificate enrollment and revocation, and ++certificate and CRL access. ++ ++In the following, Section 2 gives an overview of the PKI operations, ++and Section 2.4 describes the security goals of the protocol and the ++mechanisms used to achieve them. The transport protocol and the ++security protocol PKCS#7 are described at Section 3 and Section 4, ++respectively. The last section, Section 5, specifies each PKI ++operation in terms of the message formats and the data structures of ++each operation. ++ ++The appendices provide detailed specifications and examples. Requester ++subject names are specified in Appendix A, attribute OIDs are ++specified in Appendix C , and the SCEP state transitions are described ++in Appendix E. An example of a certificate enrollment request is ++provided in Appendix B, and an example LDAP query URL encoding is ++provided in Appendix D. ++ ++The authors would like to thank Peter William of ValiCert, Inc. ++(formerly of Verisign, Inc) and Alex Deacon of Verisign, Inc. and ++Christopher Welles of IRE, Inc. for their contributions to this protocol ++and to this document. ++ ++ Liu/Madson/McGrew/Nourse [Page 3] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++2.0 The Goal of SCEP ++The goal of SCEP is to support the secure issuance of certificates to ++network devices in a scalable manner, using existing technology whenever ++possible. The protocol supports the following operations: ++ ++ CA and RA public key distribution ++ Certificate enrollment ++ Certificate revocation ++ Certificate query ++ CRL query ++ ++Certificate and CRL access can be achieved by using the LDAP protocol ++(as specified in Appendix D), or by using the query messages defined in ++SCEP. The use of HTTP certificate and CRL access, and the support of ++CDP as specified in RFC2459, will be specified in a future version of ++this document. In Section 2.1, we first define PKI entity types as well ++as the properties of each entity type. In Section 2.2, the PKI ++operations are described at functional level. Section 2.3 describes the ++transaction behavior of each PKI operations. The complete PKI messages ++are covered in Section 5. ++ ++2.1 SCEP Entity types ++ ++The entity types defined in SCEP are the "requester" type (i.e., IPSEC ++clients), the Certificate Authority (CA) entity type, and the ++Registration Authority entity type (RA). A requester is sometimes ++called a "SCEP client" in the following. ++ ++2.1.1 Requesters ++ ++A requester is an entity whose name is defined in a certificate ++subject name field and optionally, in SubjectAltName, a X.509 ++certificate V3 extension. As a requester, a SCEP client is identified ++by a subject name consisting of the following naming attributes: ++ ++ Fully qualified domain name, for example, router.cisco.com ++ IP address, Serial number, and/or x.500 distinguished name ++ ++The fully qualified domain name is required for a requester that intends ++to use the certificate for ISAKMP. The IP address, serial number, and ++x.500 distinguished name are optional name attributes. In the ++certificate enrollment request, the PKCS#10 subject field contains the ++required and optional name attributes. The distinguished name, if any, ++should be the subject name field, while any domain name, serial number, ++or IP address supplied should be in the subjectAltName field. The ++subject name field may be empty (if there is no distinguished name) ++or the subjectAltName may be omitted, but not both. ++ ++It is important to note that a client named as Alice.cisco.com is ++different than a client named as Alice.cisco.com plus the IP address ++name attribute 117.96.1.219. From CA point of view, the Distinguished ++names assigned in these two cases are distinct names. ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 4] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++Entity names which are specified as in the IPSEC profile (i.e., FQDN, IP ++address and User FQDN) must be presented in certificate's SubjectAltName ++extension. Multiple IPSEC entity names, (if any) are encoded as multiple ++values of a single SubjectAltName extension. The CA has the authority ++to assign a distinguished name to a requester, whether or not one was ++included in the request. The assigned DN should contain the SCEP client ++names as the relative DN. ++ ++The attribute identifiers and an example of SCEP client subject name are ++specified in Appendix A. Appendix B has an example from Cisco VPN Client ++enrollment request. ++ ++2.1.1.1 Local Key/Certificate/CRL Storage and Certificate-name uniqueness ++ ++A requester is required to generate asymmetric key pairs and to provide ++storage to store its private keys. If the requester does not have enough ++permanent memory to save its certificate, then it should be able to query ++its own certificate from the CA or an LDAP server, once the certificate ++has been issued. The public key pairs can be generated with a specific ++key usage. The key usage is conveyed to the CA through the certificate ++enrollment request. All current SCEP client implementations expect that ++there will be only one pair of keys for a given subject name ++and key usage combination and CA, at any time. This property is called ++the certificate-name uniqueness property, and it implies that a CA that ++implements SCEP will enforce the unique mapping between a SCEP client ++subject name and its key pairs with a given key usage. At any time, if ++the subject name is changed, or if the key is updated, the existing ++certificate would have to be revoked before a new one could be issued. ++ ++It is desirable that the CA enforce certificate-name uniqueness, but ++it is not mandatory. However a CA that does not enforce uniqueness ++must provide some other mechanism to prevent the re-transmission of an ++enrollment request by a SCEP client from creating a second certificate ++or certificate request, nor can the second request merely be rejected. ++If a client times out from polling for a pending request it can ++resynchronize by reissuing the original request with the original ++subject name, key, and transaction ID. This should return the status of ++the original transaction, including the certificate if it was granted. ++It should not create a new transaction unless the original cert has been ++revoked, or the transaction arrives more than halfway through the ++validity time of the original certificate. ++ ++An enrollment request that occurs more than halfway through the validity ++time of an existing certificate for the same subject name and key usage ++MAY be interpreted as a re-enrollment or renewal request and accepted. ++A new certificate with new validity dates may be issued, even though ++the old one is still valid, if the CA policy permits, as described in ++2.1.1.3. See also appendix G. ++ ++2.1.1.2 Requester authentication ++ ++As with every protocol that uses public-key cryptography, the ++association between the public keys used in the protocol and the ++identities with which they are associated must be authenticated in a ++ Liu/Madson/McGrew/Nourse [Page 5] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++cryptographically secure manner. This requirement is needed to ++prevent a "man in the middle" attack, in which an adversary that can ++manipulate the data as it travels between the protocol participants ++can subvert the security of the protocol. To satisfy this ++requirement, SCEP provides two authentication methods: manual ++authentication, and authentication based on pre-shared secret. In the ++manual mode, the requester is required to wait until its identity can ++be verified by the CA operator using any reliable out-of-band ++method. To prevent a "man-in-the-middle" attack, a SHA-1 or MD5 ++`fingerprint' generated on the PKCS#10 (before PKCS #7 enveloping and ++signing) must be compared out-of-band between the server and the ++requester. SCEP clients and CAs (or RAs, if appropriate) must display ++this fingerprint to the operator to enable this verification if manual ++mode is used. Failing to provide this information leaves the protocol ++vulnerable to attack by sophisticated adversaries. When utilizing a ++pre-shared secret scheme, the server should distribute a shared secret ++to the requester which can uniquely associate the enrollment request ++with the given end entity. The distribution of the secret must be ++private: only the end entity should know this secret. The actual ++binding mechanism between the requester and the secret is subject to ++the server policy and implementation. When creating the enrollment ++request, the requester is asked to provide a challenge password. When ++using the pre-shared secret scheme, the requester must enter the ++re-distributed secret as the password. In the manual authentication ++case, the challenge password only used to authenticate a request for ++the certificate's revokation. This challenge password is included as ++a PKCS#10 attribute, and is sent to the server as encrypted data. The ++PKCS#7 envelope protects the privacy of the challenge password with ++DES encryption. ++ ++2.1.1.3 Requester Uses Existing CA-Issued or Self-Signed Certificates ++ ++In this protocol, the communication between the requester and the ++certificate authority is secured by using PKCS#7 as the messaging ++protocol. PKCS#7, however, is a protocol which assumes the ++communicating entities already possess the peer's certificates and ++requires both parties use the issuer names and issuer assigned ++certificate serial numbers to identify the certificate in order to ++verify the signature and decrypt the message. If the requesting ++system already has a certificate issued by the CA, that certificate ++may be presented as credentials for the renewal of that certificate if ++the CA supports the "Renewal" capability and the CA policy permits the ++certificate to be renewed. If the requester has no certificate issued ++by the CA, or if the CA does not support and permit renewal, the ++requestor must generate a self-signed certificate with the requester ++subject name (the same name later used in the PKCS#10) as both issuer ++and subject name. During the certificate enrollment, the requester ++will first post itself as the signing authority by attaching the ++self-signed certificate to the signed certificate request. When the ++Certificate Authority makes the envelope on the issued certificate ++using the public key included in the self-signed certificate, it ++should use the same issuer name and serial number as conveyed in the ++self-signed certificate to inform the end entity on which private key ++should be used to open the envelope. ++ Liu/Madson/McGrew/Nourse [Page 6] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++Note that when a client enrolls for separate encryption and signature ++certificates, it may use the signature certificate to sign both ++requests, and then expect its signature key to be used to encrypt ++both responses. In any case, the recipientinfo on the envelope should ++reflect the key used to encrypt the request. ++ ++2.1.1.4 Trusted CA Store ++ ++To support interoperability between IPSEC peers whose certificates are ++issued by different CA, SCEP allows the users to configure multiple ++trusted certificates. Trusted certificates are have been configured as ++such in the client, based on some out-of-band means such as a "fingerprint". ++These trusted certificates are used to verify certificate chains that end ++in those certificates. ++ ++2.1.2 Certificate Authority ++ ++A Certificate Authority(CA) is an entity whose name is defined in the ++certificate issuer name field. Before any PKI operations can begin, ++the CA generates its own public key pair and creates a self-signed CA ++certificate, or causes another CA to issue a certificate to it. ++Associated with the CA certificate is a fingerprint which will be used ++by the requester to authenticate the received CA certificate if it is ++self-signed. The fingerprint is created by calculating a SHA-1 or MD5 ++hash on the whole CA certificate. Before any requester can start its ++enrollment, this CA certificate has to be configured at the entity ++side securely. For IPSEC clients, the client certificates must have ++SubjectAltName extension. To utilize LDAP as a CRL query protocol, ++the certificates must have a CRL Distribution Point. Key usage is ++optional. Without key usage, the public key is assumed as a general ++purpose public key and it can be used for all the purposes. ++ ++A Certificate Authority may enforce certain name policy. When using ++X.500 directory name as the subject name, all the name attributes ++specified in the PKCS#10 request should be included as Relative DN. All ++the name attributes as defined in RFC2459 should be specified in the ++SubjectAltName. An example is provided in Appendix A. ++ ++ If there is no LDAP query protocol support, the Certificate Authority ++should answer certificate and CRL queries, and to this end it should be ++online all the time. ++ ++The updating of the CA's public key is addressed in Appendix G. ++ ++2.1.3 Registration Authorities ++ ++In an environment where an RA is present, a requester performs ++enrollment through the RA. In order to setup a secure channel with an RA ++using PKCS#7, the RA certificate(s) have to be obtained by the client ++in addition to the CA certificate(s). ++ ++In the following, the CA and RA are specified as one entity in the ++context of PKI operation definitions. ++ Liu/Madson/McGrew/Nourse [Page 7] ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++2.2 SCEP Operations Overview ++ ++In this section, we give a high level overview of the PKI operations as ++defined in SCEP. ++ ++2.2.1 Requester Initialization ++ ++The requester initialization includes the key pair generation and the ++configuring of the required information to communicate with the ++certificate authority. ++ ++2.2.1.1 Key Pairs ++ ++Before a requester can start PKI transaction, it must have at least one ++asymmetric key pair, using the selected algorithm (the RSA algorithm is ++required in SCEP, and is the only algorithm in current implementations). ++ ++Key pairs may be intended for particular purposes, such as encryption only, ++or signing only. The usage of any associated certificate can be restricted ++by adding key usage and extended key usage attributes to the PKCS#10. ++ ++2.2.1.2 Required Information ++ ++A requester is required to have the following information configured ++before starting any PKI operations: ++ ++1. the certificate authority IP address or fully-qualified domain name, ++2. the certificate authority HTTP CGI script path, and ++ the HTTP proxy information in case there is no direct Internet ++ connection to the server, ++3. If CRLs are being published by the CA to an LDAP directory server, ++ and there is a CRL Distribution Point containing only an X.500 directory ++ name, then the client will need to know the LDAP server fully-qualified ++ domain name or IP address. CRL Distribution Points are discussed in ++ more detail in RFC 2459. ++ ++ ++2.2.2 CA/RA Certificate Distribution ++ ++Before any PKI operation can be started, the requester needs to get ++the CA/RA certificates. At this time, since no public key has been ++ ++ Liu/Madson/McGrew/Nourse [Page 8] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++exchanged between the requester and the CA/RA, the message to get the ++CA/RA certificate can not be secured using PKCS#7 protocol. Instead, the ++CA/RA certificate distribution is implemented as a clear HTTP Get ++operation. After the requester gets the CA certificate, it has to ++authenticate the CA certificate by comparing the finger print with the ++CA/RA operator. Since the RA certificates are signed by the CA, there is ++no need to authenticate the RA certificates. ++ ++This operation is defined as a transaction consisting of one HTTP Get ++message and one HTTP Response message: ++ ++ REQUESTER CA SERVER ++ Get CA/RA Cert: HTTP Get message ++ -----------------------------> ++ CA/RA Cert download: HTTP Response message ++ <--------------------------------------- ++ Compute finger print and ++ call CA operator. ++ Receive call and check finger print ++ ++If an RA is in use, a degenerated PKCS#7 with a certificate chain ++consisting of both RA and CA certificates is sent back to the end ++entity. Otherwise the CA certificate is directly sent back as the ++HTTP response payload. ++ ++ ++2.2.3 Certificate Enrollment ++ ++A requester starts an enrollment transaction by creating a certificate ++request using PKCS#10 and sends it to the CA/RA enveloped using the ++PKCS#7. After the CA/RA receives the request, it will either ++automatically approve the request and send the certificate back, or it ++will require the requester to wait until the operator can manually ++authenticate the identity of the requester. Two attributes are ++included in the PKCS#10 certificate request - a Challenge Password ++attribute and an optional ExtensionReq attribute which will be a ++sequence of extensions the requester would like to be included in its ++V3 certificate extensions. The Challenge Password may be used to ++authenticate either the enrollment request itself, or a verbal ++revocation request for the issued certificate in the event of key ++compromise or other reason. ++ ++In the automatic mode, the transaction consists of one PKCSReq PKI ++Message, and one CertRep PKI message. In the manual mode, the requester ++enters into polling mode by periodically sending a GetCertInitial PKI ++message to the server, until the server operator completes the manual ++authentication, after which the CA will respond to GetCertInitial by ++returning the issued certificate. A CA MAY run in automatic mode for ++preapproved requests, and manual mode for the rest. A request with a ++non-null password is not necessarily a pre-approved request. It is up ++to the CA server to decide. Polling mode is entered whenever the ++server returns a PENDING response. ++ ++ Liu/Madson/McGrew/Nourse [Page 9] ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ ++The transaction in automatic mode: ++ ++ REQUESTER CA SERVER ++ ++PKCSReq: PKI cert. enrollment msg ++ --------------------------------> CertRep: pkiStatus = SUCCESS ++ certificate attached ++ <------------------------------ ++ Receive issued certificate. ++ ++The transaction in manual mode: ++ ++ REQUESTER CA SERVER ++ PKCSReq: PKI cert. enrollment msg ++ --------------------------------> CertRep: pkiStatus = PENDING ++ <------------------------------ ++ GetCertInitial: polling msg ++ --------------------------------> CertRep: pkiStatus = PENDING ++ <------------------------------ ++ ................. CertRep: pkiStatus = SUCCESS ++ certificate attached ++ <------------------------------ ++ Receive issued certificate. ++ ++2.2.4 Requester Certificate Revocation ++ ++A requester should be able to revoke its own certificate. Currently ++the revocation is implemented as a manual process. In order to revoke a ++certificate, the requester makes a phone call to the CA server ++operator. The operator will come back asking the ChallengePassword ++(which has been sent to the server as an attribute of the PKCS#10 ++certificate request). If the ChallengePassword matches, the certificate ++is revoked. The reason of the revocation is documented by CA/RA. ++ ++2.2.5 Certificate Access ++ ++There are two methods to query certificates. The first method is to use ++LDAP as a query protocol. Using LDAP to query assumes the client ++understand the LDAP scheme supported by the CA. The SCEP client assumes ++that the subject DN name in the certificate is used as the URL to query the ++certificate. The standard attributes (userCertificate and caCertificate) ++are used as filter. ++ ++For the environment where LDAP is not available, a certificate query ++message is defined to retrieve the certificates from the CA. ++ ++To query a certificate from the certificate authority, a requester ++sends a request consisting of the certificate's issuer name and the ++serial number. This assumes that the requester has saved the issuer ++ ++ Liu/Madson/McGrew/Nourse [Page 10] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++name and the serial number of the issued certificate from the previous ++enrollment transaction. The transaction to query a certificate consists ++of one GetCert PKI message and one CertRep PKI message: ++ ++ REQUESTER CA SERVER ++ GetCert: PKI cert query msg ++ -------------------------------> CertRep: pkiStatus = SUCCESS ++ certificate ++attached ++ <----------------------------- ++ Receive the certificate. ++ ++2.2.6 CRL Distribution ++ ++The CA/RA will not "push" the CRL to the end entities. The query of the ++CRL can only be initialized by the requester. ++ ++There are three methods to query CRL. ++ ++The CRL may be retrieved by a simple HTTP GET. If the CA supports this ++method, it should encode the URL into a CRL Distribution Point extension ++in the certificates it issues. Support for this method should be ++incorporated in new and updated clients, but may not be in older ++versions. ++ ++The second method is to query CRL using LDAP. This assumes the CA server ++supports CRL LDAP publishing and issues the CRL Distribution Point in ++the certificate. The CRL Distribution Point is encoded as a DN. Please ++refer to Appendix D for the examples of CRL Distribution Point. ++ ++The third method is implemented for the CA which does not support LDAP ++CRL publishing or does not implement the CRL Distribution Point. In this ++case, a CRL query is composed by creating a message consists of the CA ++issuer name and the CA's certificate serial number. This method is ++deprecated because it does not scale well and requires the CA to be a ++high-availability service. ++ ++The message is sent to the CA in the same way as the other SCEP ++requests: The transaction to query CRL consists of one GetCRL PKI ++message and one CertRep PKI message which have no certificates but CRL. ++ ++ REQUESTER CA SERVER ++ GetCRL: PKI CRL query msg ++ ----------------------------------> CertRep: CRL attached ++ <-------------------------------- ++ ++2.3 PKI Operation Transactional Behavior ++ ++As described before, a PKI operation is a transaction consisting of the ++messages exchanged between a requester and the CA/RA. This section ++will specify the transaction behavior on both the requester and the ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 11] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++certificate authority server. Because the protocol is basically a two ++way communication protocol without a confirmation message from the ++initiating side, state and state resynchronization rules have to be ++defined, in case any error happens at either side. Before the state ++transition can be defined, the notion of transaction identifier has to ++be defined first. ++ ++2.3.1 Transaction Identifier ++ ++A transaction identifier is a string generated by the entity when ++starting a transaction. Since all the PKI operations defined in this ++protocol are initiated by the requester, it is the responsibility of ++the requester to generate a unique string as the transaction ++identifier. All the PKI messages exchanged for a given PKI transaction ++must carry the same transaction identifier. The transaction identifier ++is generated as a SHA-1 or MD5 hash on the public key value for which the ++enrollment request is made. This allows the SCEP client to reuse the ++same transaction identifier if it is reissuing a request for the same ++certificate (i.e. a certificate with the same subject, issuer, and key). ++The SCEP protocol requires that transaction identifiers be unique, so ++that queries can be matched up with transactions. For this reason, in ++those cases in which separate signing and encryption certificates are ++issued to the same requester, the keys must be different. ++ ++2.3.2 State Transitions in Certificate Enrollment ++ ++The requester state transitions during enrollment operation are ++indicated in the diagram below: ++ +-<------+ ++ | | ++ GetCertInitial triggered by timeout or ++ | | manual authentication ++ | | ++ [CERT-NONEXISTANT] ------> [CERT-REQ-PENDING] ---> [CERT-ISSUED] ++ | PKCSReq | CertRep with SUCCESS ++ | | ++ | | ++ +--------<-------------------+ ++ request rejected, timeout, or error ++ ++As described in the section 2.2.3, certificate enrollment starts at the ++state CERT-NONEXISTANT. Sending PKCSReq changes the state to ++CERT-REQ-PENDING. Receiving CertRep with SUCCESS status changes the ++state to CERT-ISSUED. In the case the server sending back the response ++with pending status, the requester will keep polling certificate ++response by sending GetCertInitial to the server, until either a CertRep ++with SUCCESS status is received, or the maximum polling number has been ++exceeded. ++ ++If an error or timeout occurs in the CERT-REQ-PENDING state, the end ++entity will transition to the CERT-NONEXISTANT state. ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 12] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ ++The client administrator will, eventually, start up another enrollment ++request. It is important to note that, as long as the requester does ++not change its subject name or keys, the same transaction id will be ++used in the "new" transaction. This is important because based on this ++transaction id, the certificate authority server can recognize this as ++an existing transaction instead of a new one. ++ ++ ++2.3.3 Transaction Behavior of Certificate/CRL Access ++ ++There is no state maintained during certificate access and CRL access ++transaction. When using the certificate query and CRL query messages ++defined in this protocol, the transaction identifier is still required ++so that the requester can match the response message with the ++upstanding request message. When using LDAP to query the certificate and ++the CRL, the behavior is specified by the LDAP protocol. ++ ++2.4 Security ++ ++The security goals of SCEP are that no adversary can: ++ ++o subvert the public key/identity binding from that intended, ++o discover the identity information in the enrollment requests and ++ issued certificates, ++o cause the revocation of certificates with any non-negligible ++ probability. ++ ++Here an adversary is any entity other than the requester and the CA ++(and optionally the RA) participating in the protocol that is ++computationally limited, but that can manipulate data during ++transmission (that is, a man-in-the-middle). The precise meaning of ++'computationally limited' depends on the implementer's choice of ++cryptographic hash functions and ciphers. The required algorithms are ++RSA, DES, and either SHA-1 or MD5, depending on the "SHA-1" CA Capability. ++[See Appendix F]. ++ ++The first and second goals are met through the use of PKCS#7 and PKCS#10 ++encryption and digital signatures using authenticated public keys. The ++CA's public key is authenticated via the checking of the CA fingerprint, ++as specified in Section 2.1.2, and the SCEP client's public key is ++authenticated through the manual authentication or pre-shared secret ++authentication, as specified in Section 2.1.1.2. The third goal is met ++through the use of a Challenge Password for revocation, that is chosen ++by the SCEP client and communicated to the CA protected by the PKCS#7 ++encryption, as specified in Section 2.2.4. ++ ++The motivation of the first security goal is straightforward. The ++motivation for the second security goal is to protect the identity ++information in the enrollment requests and certificates. For example, ++two IPSEC hosts behind a firewall may need to exchange certificates, and ++may need to enroll certificates with a CA that is outside of a firewall. ++Most networks with firewalls seek to prevent IP addresses and DNS ++ ++ Liu/Madson/McGrew/Nourse [Page 13] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++information from the trusted network leaving that network. The second ++goal enables the hosts in this example to enroll with a CA outside the ++firewall without revealing this information. The motivation for the ++third security goal is to protect the SCEP clients from denial of ++service attacks. ++ ++Section 3 Transport Protocol ++ ++In the SCEP protocol, HTTP is used as the transport protocol for the PKI ++messages. ++ ++3.1 HTTP "GET" and "POST" Message Format ++ ++The following is the syntax definition of a HTTP GET message sent from ++a requester to a certificate authority server: ++ ++Request = "GET " CGI-PATH CGI-PROG "?operation=" OPERATION "&message=" MESSAGE ++where: ++ CGI-PATH defines the actual CGI path to invoke the CGI program which ++ parses the request. ++ CGI-PROG is set to be the string "pkiclient.exe". This is intended ++ to be the program that the CA will use to handle the SCEP transactions, ++ though the CA may ignore CGI-PROG and use only the CGI-PATH. ++ OPERATION is set to be the string "PKIOperation" when the GET message ++ carries a PKI message to request certificates or CRL; OPERATION is set ++ to be the string "GetCACaps", "GetCACert", "GetNextCACert" or ++ "GetCACertChain" when the GET operation is used to get CA capabilities, ++ CA/RA certificate, the replacement CA/RA certificates for when the ++ current ones expire, or the CA Cert chain (respectively). ++ ++ When OPERATION is "PKIOperation", MESSAGE is a base64-encoded PKI message, ++ When OPERATION is GetCACert, MESSAGE is a CRL distribution ++ point in URI format, otherwise, MESSAGE is a string which represents ++ the certificate authority issuer identifier. ++ ++SCEP uses the HTTP "GET" and "POST" messages to request information from the CA. ++Requests for CA certificates or capabilities are sent in the clear, using "GET", ++with the OPERATION and MESSAGE fields identifying the requested data. ++CRLs may also be requested in the clear if the CA supports it. ++ ++Other types of requests are sent using the PKCS#7 secure protocol. ++These may be issued by means of a GET operation with ++OPERATION and MESSAGE parameters in the Request-URL. OPERATION ++identifies the type of GET operation, and MESSAGE is actually the PKCS#7 ++message Base64-Encoded. ++ ++For example. a requester may submit a message via HTTP to the server ++as follows: ++ ++GET /cgi-bin/pkiclient.exe?operation=PKIOperation&message=MIAGCSqGSIb3D ++QEHA6CAMIACAQAxgDCBzAIBADB2MGIxETAPBgNVBAcTCE ......AAAAAA== ++ Liu/Madson/McGrew/Nourse [Page 13a] ++ ++If supported by the CA, the message may also be sent via HTTP POST: ++ ++POST /cgi-bin/pkiclient.exe?operation=PKIOperation ++ ++This is further described in Appendix H. ++To determine if the CA supports POST, use the GetCACaps message described ++in Appendix F. ++ ++ ++3.2 Response Message Format ++ ++For each GET operation, the CA/RA server will return a MIME object via ++HTTP. For a GET operation with PKIOperation as its type, the response is ++tagged as having a Content Type of application/x-pki-message. The body ++of this message is a BER encoded binary PKI message. The following is an ++example of the response: ++ ++"Content-Type:application/x-pki-message\n\n" ++ ++In the case of GET operation with a type of GetCACert the MIME content ++type returned will depend on whether or not an RA is in use. If there ++is no RA, only the CA certificate is sent back in the response, and ++the response has the content type tagged as ++application/x-x509-ca-cert. the body of the response is a DER encoded ++binary X.509 certificate. For example: ++ ++"Content-Type:application/x-x509-ca-cert\n\n" ++ ++If there is an RA, the RA certificates are sent back together with the ++CA certificates, a certificate-only PKCS#7 SignedData is sent back in ++the response where the SignerInfo is empty. Section 5 has the detailed ++definition of the message format in this case. The content type is ++application/x-x509-ca-ra-cert. ++ ++The response to GetNextCACert is always a certificates-only PKCS#7 ++SignedData with a content type of application/x-x509-ca-ra-cert. ++If there is an RA, The signer is the current RA certificate. Otherwise, ++the signer is the current CA certificate. ++ ++If the CA supports it, PKIOperation may also be done via an HTTP POST. ++This is described in Appendix H. ++ ++ Liu/Madson/McGrew/Nourse [Page 14] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++Section 4 Secure Transportation: PKCS#7 ++ ++PKCS#7 is a general enveloping mechanism that enables both signed and ++encrypted transmission of arbitrary data. It is widely implemented and ++included in the RSA tool kit. In this section, the general PKCS#7 ++enveloped PKI message format is specified. The complete PKCS#7 message ++format for each PKI transaction will be covered in Section 5. ++ ++4.1 SCEP Message Format ++ ++As a transaction message, a SCEP message has a set of transaction ++specific attributes and an information portion. Employing PKCS#7 ++protocol, the transaction specific attributes are encoded as a set of ++authenticated attributes of the SignedData. The information portion will ++first be encrypted to become Enveloped Data, and then the digest of the ++enveloped information portion is included as one of the message digest ++attributes and being signed together with the other transaction specific ++attributes. ++ ++By applying both enveloping and signing transformations, a SCEP message ++is protected both for the integrity of its end-end-transition ++information and the confidentiality of its information portion. The ++advantage of this technique over the conventional transaction message ++format is that, the signed transaction type information and the status ++of the transaction can be determined prior to invoke security handling ++procedures specific to the information portion being processed. ++ ++The following is an example of a SCEP message with its enveloped and ++signed data portion represented by pkcsPKISigned and ++pkcsPKIEnveloped. The out-most of any PKI message is a blob of ++ContentInfo, with its content type set to SignedData and the actual ++signed data as the content. ++ ++ Liu/Madson/McGrew/Nourse [Page 15] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ pkiMessage ContentInfo ::= { ++ contentType {pkcs-7 signedData(2)} ++ content pkcsPKISigned ++ } ++ pkcsPKISigned SignedData ::= { ++ version 1 ++ digestAlgorithm { iso(1) member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ contentInfo { ++ contentType {pkcs-7 1} -- data content identifier ++ content pkcsPKIEnvelope -- enveloped information portion ++ } ++ certificates -- signer certificate chain ++ signerInfo -- including signed transaction info and the digest ++ -- of the enveloped information portion as the ++ -- authenticated attributes ++ } ++ pkcsPKIEnveloped EnvelopedData ::= { ++ version 0 ++ recipientInfos -- information required to open the envelop ++ encryptedContentInfo { ++ contentType {pkcs-7 1} -- data content identifier ++ contentEncryptionAlgorithm ++ encryptedContent -- encrypted information portion ++ } ++ } ++ ++4.2 Signed Transaction Attributes ++ ++The following transaction attributes are encoded as authenticated ++attributes. Please refer to Appendix B for the OID definitions. ++ ++transactionID PrintableString -- Decimal value as a string ++ messageType PrintableString -- Decimal value as a string ++ pkiStatus PrintableString -- Decimal value as a string ++ failinfo PrintableString -- Decimal value as a string ++ senderNonce Octet String ++ recipientNonce Octet String ++ ++where: ++ ++ The transactionID is an attribute which uniquely identify a ++ transaction. This attribute is required in all PKI messages. ++ ++ The messageType attribute specify the type of operation performed by the ++ transaction. This attribute is required in all PKI ++ messages. Currently, the following message types are defined: ++ ++ PKCSReq (19) -- Permits use of PKCS#10 certificate request ++ CertRep (3) -- Response to certificate or CRL request ++ GetCertInitial (20) -- Certificate polling in manual enrollment ++ GetCert (21) -- Retrieve a certificate ++ GetCRL (22) -- Retrieve a CRL ++ ++ Liu/Madson/McGrew/Nourse [Page 16] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ ++ All response message will include transaction status information which ++ is defined as pkiStatus attribute: ++ ++ SUCCESS (0) -- request granted ++ FAILURE (2) -- request rejected ++ PENDING (3) -- request pending for manual approval. ++ ++ If the status in the response is FAILURE, the failinfo attribute will ++ contain one of the following failure reasons: ++ ++ badAlg (0) -- Unrecognized or unsupported algorithm ident ++ badMessageCheck (1) -- integrity check failed ++ badRequest (2) -- transaction not permitted or supported ++ badTime (3) -- Message time field was not sufficiently close ++ to the system time ++ badCertId (4) -- No certificate could be identified matching ++ the provided criteria ++ ++ The attributes of senderNonce and recipientNonce are the 16 byte ++ random numbers generated for each transaction to prevent the replay ++ attack. ++ ++When a requester sends a PKI message to the server, a senderNonce is ++included in the message. After the server processes the request, it will ++send back the requester senderNonce as the recipientNonce and generates ++another nonce as the senderNonce in the response message. Because the ++proposed pki protocol is a two-way communication protocol, it is clear ++that the nonce can only be used by the requester to prevent the ++replay. The server has to employ extra state related information to ++prevent a replay attack. ++ ++Section 5. SCEP Transaction Specification ++ ++In this section each SCEP transaction is specified in terms of the ++complete messages exchanged during the transaction. ++ ++5.1 Certificate Enrollment ++ ++The certificate enrollment transaction consists of one PKCSReq message ++sent to the certificate authority from a requester, and one CertRep ++message sent back from the server. The pkiStatus returned in the ++response message is either SUCCESS, or FAILURE, or PENDING. The ++information portion of a PKCSReq message is a PKCS#10 certificate ++request, which contains the subject Distinguished Name, the subject ++public key, and two attributes, a ChallengePassword attribute to be used ++for revocation, and an optional ExtensionReq attribute which will be a ++sequence of extensions the requester expects to be included in its V3 ++certificate extensions. One of the extension attribute specifies the key ++usage. If the request is granted, the pkiStatus is set to SUCCESS, and ++the certificate is returned in CertRep; if the request is rejected, the ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 17] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++pkiStatus is set to FAILURE; if the server requires manual approval of ++the request, the pkiStatus is set to PENDING. The messages exchanged ++in the manual authentication mode is further specified in Section 5.2. ++ ++Precondition: ++ Both the requester and the certificate authority have completed their ++ initialization process. The requester has already been configured ++ with the CA/RA certificate. ++ ++Postcondition: ++ Either the certificate is received by the requester, or the end ++ entity is notified to do the manual authentication, or the request ++ is rejected. ++ ++5.1.1 PKCSReq Message Format ++ ++A PKCSReq message is created by following the steps defined below: ++ ++1. Create a PKCS#10 certificate request which is signed by the end ++ entity's private key, corresponding to the public key included in ++ the PKCS#10 certificate request. This constitutes the information ++ portion of PKCSReq. ++ ++2. Encrypt the PKCS#10 certificate request using a randomly generated ++ content-encryption key. This content-encryption key is then ++ encrypted by the CA's* public key and included in the recipientInfo. ++ This step completes the "envelope" for the PKCS#10 certificate ++ request. ++ ++3. Generate a unique string as the transaction id. ++ ++4. Generate a 16 byte random number as senderNonce. ++ ++5. Generate message digest on the enveloped PKCS#10 certificate request ++ using the selected digest algorithm. ++ ++6. Create SignedData by adding the requester's self- or CA-certificate ++ as the signer's public key certificate. Include the message type, ++ transaction id, the senderNonce and the message digest as the ++ authenticated attributes and sign the attributes using the end ++ entity's private key. This completes the SignedData. ++ ++7. The SignedData is prepended with the ContenInfo blob which indicates ++ a SignedData object. This final step completes the create of a ++ complete PKCSReq PKI message. ++ ++In the following, the PKCSReq message is defined following the ASN.1 ++notation. ++ ++For readability, the values of a field is either represented by a quoted ++string which specifies the intended value, or a constant when the value ++is known. ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 18] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ -- PKCSReq information portion ++ pkcsCertReq CertificationRequest ::= { -- PKCS#10 ++ version 0 ++ subject "the requester's subject name" ++ subjectPublicKeyInfo { ++ algorithm {pkcs-1 1} -- rsa encryption ++ subjectPublicKey "DER encoding of the requester's public key" ++ } ++ attributes { ++ challengePassword {{pkcs-9 7} "password string" } ++ extensions ++ } ++ signatureAlgorithm {pkcs-1 4} -- MD5WithRSAEncryption ++ signature "bit string which is created by signing inner content ++ of the defined pkcsCertReq using requester's private ++ key, corresponding to the public key included in ++ subjectPublicKeyInfo." ++ } ++ -- Enveloped information portion ++ pkcsCertReqEnvelope EnvelopeData ::= { -- PKCS#7 ++ version 0 ++ recipientInfo { ++ version 0 ++ issuerAndSerialNumber { ++ issuer "the CA issuer name" ++ serialNumber "the CA certificate serial number" ++ } ++ keyEncryptionAlgorithm {pkcs-1 1} -- rsa encryption ++ encryptedKey "content-encryption key ++ encrypted by CA public key" ++ } ++ encryptedContentInfo { ++ contentType {pkcs-7 1} -- data content ++ contentEncryptionAlgorithm "object identifier ++ for DES encryption" ++ encryptedContent "encrypted pkcsCertReq using the content- ++ encryption key" ++ } ++ } ++ -- Signed PKCSReq ++ pkcsCertReqSigned SignedData ::= { -- PKCS#7 ++ version 1 ++ digestAlgorithm {iso(1) member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ contentInfo { ++ contentType {pkcs-7 1} -- data content identifier ++ content pkcsCertReqEnvelope ++ } ++ certificate { -- requester self-signed or CA-issued certificate ++ version 3 ++ serialNumber "the transaction id associated with enrollment" ++ signature {pkcs-1 4} -- md5WithRSAEncryption ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 19] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ issuer " the requester's subject name" ++ validity { ++ notBefore "a UTC time" ++ notAfter "a UTC time" ++ } ++ subject "the requester's subject name" ++ subjectPublicKeyInfo { ++ algorithm {pkcs-1 1} ++ subjectPublicKey "DER encoding of requester's public key" ++ } ++ signatureAlgorithm {pkcs-1 4} ++ signature "the signature generated by using the requester's ++ private key corresponding to the public key in ++ this certificate." ++ } ++ signerInfo { ++ version 1 ++ issuerAndSerialNumber { ++ issuer "the requester's subject name" ++ serialNumber "the transaction id associated ++ with the enrollment" ++ } ++ digestAlgorithm {iso(0) member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ authenticateAttributes { ++ contentType {{pkcs-9 3} {pkcs-7 1}} ++ messageDigest {{pkcs-9 4} "an octet string"} ++ transaction-id {{id-attributes transId(7)} "printable ++ string"} ++ -- this transaction id will be used ++ -- together with the subject name as ++ -- the identifier of the requester's key ++ -- pair during enrollment ++ messageType {{id-attributes messageType(2)} "PKCSReq"} ++ senderNonce {{id-attributes senderNonce(5)} ++ "a random number encoded as a string"} ++ } ++ digestEncryptionAlgorithm {pkcs-1 1} -- rsa encryption ++ encryptedDigest "encrypted digest of the authenticated ++ attributes using requester's private key" ++ } ++ } ++ pkcsReq PKIMessage ::= { ++ contentType {pkcs-7 2} ++ content pkcsCertRepSigned ++ } ++ ++ ++ ++ ++ ++ ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 20] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++5.1.2 CertRep Message Format ++ ++The response to an SCEP enrollment request is a CertRep message. ++ ++5.1.2.1 PENDING Response ++ ++When the CA is configured to manually authenticate the requester, ++the CertRep is returned with the attribute pkiStatus set to PENDING. ++The data portion for this message is null. Only the transaction ++required attributes are sent back. ++ ++CertRepSigned SignedData ::= { -- PKCS#7 ++ version 1 ++ digestAlgorithm {iso(1) member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ contentInfo {contentType {pkcs-7 1} -- empty content ++ } ++ signerInfo { ++ version 1 ++ issuerAndSerialNumber { ++ issuer "name of CA that issued the CA [RA] cert" ++ serialNumber "the serial number of the CA [RA] cert" ++ } ++ digestAlgorithm (iso(1) member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ authenticateAttributes { ++ contentType {{pkcs-9 3} {pkcs-7 1}} ++ messageDigest {{pkcs-9 4} NULL} ++ messageType {{id-attribute messageType(0)} "CertRep"} ++ transaction-id {{id-attributes transid(7)} "printablestring"} ++ --- same transaction id used in PKCSReq ++ pkiStatus {{id-attributes pkiStatus(3)} "PENDING"} ++ recipientNonce {{id-attributes recipientNonce(6)}<16 bytes>} ++ senderNonce {{id-attributes senderNonce(5)} <16 bytes>} ++ } ++ digestEncrytionAlgorithm {pkcs-1 1} ++ encryptedDigest "encrypted message digest of the authenticated ++ attributes using the CA's [RA's] private key" ++ } ++} ++CertRep PKIMessage ::= { ++ contentType {pkcs-7 2} ++ content CertRepSigned ++} ++ ++5.1.2.2 Failure Response ++ ++In this case, the CertRep sent back to the requester is same as in ++the PENDING case, except that the pkiStatus attribute is set to FAILURE, ++and the failInfo attribute should be included: ++ ++ pkistatus {{id-attributes pkiStatus(3)} "FAILURE"} ++ failInfo {{id-attributes failInfo(4)} "the reason to reject"} ++ ++ Liu/Madson/McGrew/Nourse [Page 21] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++5.1.2.3 SUCCESS response ++ ++In this case, the information portion of CertRep will be a degenerated ++PKCS#7 which contains the requester's certificate. It is then enveloped ++and signed as below: ++ ++pkcsCertRep SignedData ::= { -- PKCS#7 ++ version 1 ++ digestAlgorithm {iso(1) member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ contentInfo { -- empty content since this is degenerated PKCS#7 ++ contentType {pkcs-7 1} ++ } ++ certificates { ++ certificate { -- issued requester's certificate // must be first ++ version 3 ++ serialNumber "issued requester's certificate serial number" ++ signature {pkcs-1 4} -- md5WithRSAEncryption ++ issuer "the certificate authority issuer name" ++ validity { ++ notBefore "UTC time" ++ notAfter "UTC time" ++ } ++ subject "the requester subject name as given in PKCS#10" ++ subjectPublicKeyInfo { ++ algorithm {pkcs-1 1} ++ subjectPublicKey "a DER encoding of requester public ++ key as given in PKCS#10" ++ } ++ extensions " the extensions as given in PKCS#10" ++ signatureAlgorithm {pkcs-1 4} ++ signature " the certificate authority signature" ++ } ++ certificate "the certificate authority certificate" (optional) ++ certificate "the registration authority certificate(s)" (optional) ++ } ++} ++pkcsCertRepEnvelope EnvelopedData ::= { -- PKCS#7 ++ version 0 ++ recipientInfo { ++ version 0 ++ issuerAndSerialNumber { -- use issuer name and serial number as ++ -- conveyed in requester's self-signed ++ -- certificate, included in the PKCSReq ++ issuer "the requester's subject name" ++ serialNumber "the serial number defined by the requester in ++ its self-signed certificate" ++ } ++ keyEncryptionAlgorithm {pkcs-1 1} ++ encryptedKey "content-encrypt key encrypted by the requester's ++ public key which is same key as authenticated in ++ the requester's certificate" ++ } ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 22] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ encryptedContentInfo { ++ contentType {pkcs-7 1} -- data content identifier ++ contentEncryptionAlgorithm "OID for DES encryption" ++ encryptedContent "encrypted pkcsCertRep using content encryption ++ key" ++ } ++} ++pkcsCertRepSigned SignedData ::= { -- PKCS#7 ++ version 1 ++ digestAlgorithm {iso(1) member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ contentInfo { ++ contentType {pkcs-7 1} ++ content pkcsCertRepEnvelope ++ } ++ signerInfo { ++ version 1 ++ issuerAndSerialNumber { ++ issuer "the certificate authority issuer name" ++ serialNumber "the CA certificate's serial number" ++ } ++ digestAlgorithm {iso(1), member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ authenticateAttributes { ++ contentType {{pkcs-9 3} {pkcs-7 1}} ++ messageDigest {{pkcs-9 4} "a octet string"} ++ messageType {{id-attribute messageType(2)} "CertRep"} ++ transaction-id {{id-attributes transId(7)} "printable ++ string"} ++ -- same transaction id as given in PKCSReq ++ pkiStatus {{id-attributes pkiStatus(3) "SUCCESS"} ++ recipientNonce {{id-attribute recipientNonce(6)}<16 bytes>} ++ senderNonce {{ id-attributes senderNonce(5) <16 bytes>} ++ } ++ digestEncryptionAlgorithm {pkcs-1 1} ++ encryptedDigest "encrypted digest of authenticate attributes ++ using CA's private key " ++ } ++} ++CertRep PKIMessage ::= { ++ contentType {pkcs-7 2} ++ content pkcsCertRepSigned ++} ++ ++5.2 Poll for Requester Initial Certificate ++ ++Either triggered by the PENDING status received from the CertRep, or by ++the non-response timeout for the previous PKCSReq, a requester will ++enter the polling state by periodically sending GetCertInitial to the ++server, until either the request is granted and the certificate is sent ++back, or the request is rejected, or the configured time limit for ++polling is exceeded. ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 23] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ ++Since GetCertInitial is part of the enrollment, the messages exchanged ++during the polling period should carry the same transaction identifier ++as the previous PKCSReq. ++ ++PreCondition ++ Either the requester has received a CertRep with pkiStatus set to be ++ PENDING, or the previous PKCSReq has timed out. ++ ++PostContition ++ The requester has either received the certificate, or be rejected of ++ its request, or the polling period ended as a failure. ++ ++5.2.1 GetCertInitial Message Format ++ ++Since at this time the certificate has not been issued, the requester ++can only use the requester's subject name, combined with the ++transaction identifier, to identify the polled certificate request. ++ ++The certificate authority server must be able to uniquely identify the ++polled certificate request. A subject name can have more than one ++outstanding certificate request (with different key usage attributes). ++ ++-- Information portion ++ ++pkcsGetCertInitial issuerAndSubject ::= { ++ issuer "the certificate authority issuer name" ++ subject "the requester subject name as given in PKCS#10" ++} ++pkcsGetCertInitialEnvelope EnvelopedData ::= { ++ version 0 ++ recipientInfo { ++ version 0 ++ issuerAndSerialNumber { ++ issuer "the CA issuer name" ++ serialNumber "the CA certificate serial number" ++ } ++ keyEncryptionAlgorithm {pkcs-1 1} ++ encryptedKey "content-encrypt key encrypted by CA's public key" ++ } ++ encryptedContentInfo { ++ contentType {pkcs-7 1} -- data content ++ contentEncryptionAlgorithm "OID for DES encryption" ++ encryptedContent "encrypted getCertInital" ++ } ++} ++pkcsGetCertInitialSigned SignedData ::= { -- PKCS#7 ++ version 1 ++ digestAlgorithm {iso(1) member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ contentInfo { ++ contentType {pkcs-7 1} ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 24] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ content pkcsGetCertIntialEnvelope ++ } ++ certificate { -- the requester's self-signed certificate ++ version 3 ++ serialNumber "the transaction id associated with enrollment" ++ signature {pkcs-1 4} -- md5WithRSAEncryption ++ issuer " the requester's subject name" ++ validity { ++ notBefore "a UTC time" ++ notAfter "a UTC time" ++ } ++ subject "the requester's subject name" ++ subjectPublicKeyInfo { ++ algorithm {pkcs-1 1} ++ subjectPublicKey "DER encoding of requester's public key" ++ } ++ signatureAlgorithm {pkcs-1 4} ++ signature "the signature generated by using the requester's ++ private key corresponding to the public key in ++ this certificate." ++ } ++ signerInfo { ++ version 1 ++ issuerAndSerialNumber { ++ issuer "requester's subject name" ++ serialNumber "the transaction id used in previous PKCSReq" ++ } ++ digestAlgorithm {iso(1), member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ authenticateAttributes { ++ contentType {{pkcs-9 3} {pkcs-7 1}} ++ messageDigest {{pkcs-9 4} "an octet string"} ++ -- digest of getCertInitial ++ messageType {{id-attribute messageType(2)} "GetCertInitial"} ++ transaction-id {{id-attributes transId(7)} "printable ++ string"} ++ -- same transaction idused in previous PKCSReq ++ senderNonce {{id-attribute senderNonce(3)} 0x<16 bytes>} ++ } ++ digestEncryptionAlgorithm {pkcs-1 1} ++ encryptedDigest "encrypted digest of authenticateAttributes" ++ } ++} ++GetCertInitial PKIMessage ::= { ++ contentType {pkcs-7 2} ++ content pkcsGetCertInitialSigned ++} ++ ++ ++ ++5.2.2 GetCertInitial Response Message Format ++ ++The response messages for GetCertInitial are the same as for PKCSReq. ++ ++ Liu/Madson/McGrew/Nourse [Page 25] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++5.3 Certificate Access ++ ++The certificate query message defined in this section is an option when ++the LDAP server is not available to provide the certificate query. A ++requester should be able to query an issued certificate from the ++certificate authority, as long as the issuer name and the issuer ++assigned certificate serial number is known to the requesting end ++entity. This transaction is not intended to provide the service as a ++certificate directory service. A more complicated query mechanism would ++have to be defined in order to allow a requester to query a certificate ++using various different fields. ++ ++This transaction consists of one GetCert message sent to the server by ++a requester, and one CertRep message sent back from the server. ++ ++PreCondition ++ The queried certificate have been issued by the certificate authority ++ and the issuer assigned serial number is known. ++ ++PostCondition ++ Either the certificate is sent back or the request is rejected. ++ ++ ++5.3.1 GetCert Message Format ++ ++The queried certificate is identified by its issuer name and the issuer ++assigned serial number. If this is a query for an arbitrary requester's ++certificate, the requesting requester should includes its own CA issued ++certificate in the signed envelope. If this is a query for its own ++certificate (assume the requester lost the issued certificate, or does ++not have enough non-volatile memory to save the certificate), then the ++self-signed certificate has to be included in the signed envelope. ++ ++ pkcsGetCert issuerAndSerialNumber ::= { ++ issuer "the certificate issuer name" ++ serialNumber "the certificate serial number" ++ } ++ pkcsGetCertEnvelope EnvelopedData ::= { ++ version 0 ++ recipientInfo { ++ version 0 ++ issuerAndSerialNumber { ++ issuer "the CA [RA] issuer name" ++ serialNumber "the CA [RA] certificate serial number" ++ } ++ keyEncryptionAlgorithm {pkcs-1 1} ++ encryptedKey "content-encrypt key encrypted ++ by CA [RA] public key" ++ } ++ ++ ++ ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 26] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ ++ encryptedContentInfo { ++ contentType {pkcs-7 1} -- data content ++ contentEncryptionAlgorithm "OID for DES encryption" ++ encryptedContent "encrypted pkcsGetCert using the content ++ encryption key" ++ } ++ } ++ pkcsGetCertSigned SignedData ::= { ++ version 1 ++ digestAlgorithm {iso(1) member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ contentInfo { ++ contentType {pkcs-7 1} ++ content pkcsGetCertEnvelope ++ } ++ certificates { ++ certificate "CA issued certificate" ++ or "self-signed certificate" ++ } ++ signerInfo { ++ version 1 ++ issuerAndSerialNumber { ++ issuer "the requester's subject name" ++ serialNumber "requester's certificate serial number" ++ } ++ digestAlgorithm {iso(1), member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ authenticateAttributes { ++ contentType {{pkcs-9 3} {pkcs-7 1}} ++ messageDigest {{pkcs-9 4} "an octet string"} ++ -- digest of pkcsGetCertEnvelope ++ messageType {{id-attribute messageType(2)} "GetCert"} ++ transaction-id {{id-attributes transId(7)} "printable ++ string"} ++ senderNonce {{id-attribute senderNonce(3)} <16 bytes>} ++ } ++ digestEncryptionAlgorithm {pkcs-1 1} ++ encryptedDigest "encrypted digest of authenticateAttributes" ++ } ++ } ++ GetCert PKIMessage ::= { ++ contentType {pkcs-7 2} ++ content pkcsGetCertSigned ++ } ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 27] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ ++5.3.2 CertRep Message Format ++ ++In this case, the CertRep from the server is same as the CertRep for the ++PKCSReq, except that the server will only either grant the request or ++reject the request. Also, the recipientInfo should use the CA issuer ++name and CA assigned serial number to identify the requester's key pair ++since at this time, the requester has received its own certificate. ++ ++5.4 CRL Access ++ ++The CRL query message defined in this section is an option when the LDAP ++server is not available to provide the CRL query. In the PKI protocol ++proposed here, only the requester can initiate the transaction to ++download CRL. A requester sends GetCRL request to the server and the ++server sends back CertRep whose information portion is a degenerated ++PKCS#7 which contains only the most recent CRL. The size of CRL included ++in the CertRep should be determined by the implementation. ++ ++PreCondition ++ The certificate authority certificate has been downloaded to the end ++ entity. ++ ++PostCondition ++ CRL sent back to the requester. ++ ++5.4.1 GetCRL Message format ++ ++The CRL is identified by using both CA's issuer name and the CA ++certificate's serial number: ++ ++ pkcsGetCRL issuerAndSerialNumber { ++ issuer "the certificate authority issuer name" ++ serialNumber "certificate authority certificate's serial number" ++ } ++ ++When the CRLDistributionPoint is supported, the pkcsGetCRL is defined as ++the following: ++ ++ pkcsGetCRL SEQUENCE { ++ crlIssuer issuerAndSerialNumber ++ distributionPoint CE-CRLDistPoints ++ } ++ ++where CE-CRLDisPoints is defined in X.509, but must contain only one ++CRL distribution point. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 28] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ pkcsGetCRLEnvelope EnvelopedData ::= { ++ version 0 ++ recipientInfo { ++ version 0 ++ issuerAndSerialNumber { ++ issuer "the certificate authority (or RA) issuer name" ++ serialNumber "the CA (RA) certificate's serial number" ++ } ++ keyEncryptionAlgorithm {pkcs-1 1} ++ encryptedKey "content-encrypt key encrypted by CA (RA) public key" ++ } ++ encryptedContentInfo { ++ contentType {pkcs-7 1} -- data content ++ contentEncryptionAlgorithm "OID for DES encryption" ++ encryptedContent "encrypted pkcsGetCRL" ++ } ++ } ++ pkcsGetCRLSigned SignedData ::= { ++ version 1 ++ digestAlgorithm {iso(1) member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ contentInfo { ++ contentType {pkcs-7 1} ++ content pkcsGetCRLEnvelope ++ } ++ certificates { ++ certificate "CA-issued or self-signed requester's certificate" ++ } ++ signerInfo { ++ version 1 ++ issuerAndSerialNumber { ++ issuer "the requester's issuer name" ++ serialNumber "the requester's certificate serial number" ++ } ++ digestAlgorithm {iso(1), member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ authenticateAttributes { ++ contentType {{pkcs-9 3} {pkcs-7 1}} ++ messageDigest {{pkcs-9 4} 0x<16/20 bytes>} ++ -- digest of pkcsGetCRLEnvelope ++ messageType {{id-attribute messageType(2)} "CertCRL"} ++ transaction-id {{id-attributes transId(7)} "printable ++ string"} ++ senderNonce {{id-attribute senderNonce(3)} <16 bytes>} ++ } ++ digestEncryptionAlgorithm {pkcs-1 1} ++ encryptedDigest "encrypted digest of authenticateAttributes" ++ } ++ } ++ GetCRL PKIMessage ::= { ++ contentType {pkcs-7 2} ++ content pkcsGetCRLSigned ++ } ++ ++ Liu/Madson/McGrew/Nourse [Page 29] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ ++5.4.2 CertRep Message Format ++ ++The CRL is sent back to the requester through CertRep message. The ++information portion of this message is a degenerated PKCS#7 SignedData ++which contains only a CRL. ++ ++ pkcsCertRep SignedData ::= { ++ version 1 ++ digestAlgorithm {iso(1) member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ contentInfo { ++ contentType {pkcs-7 1} ++ } ++ crl { ++ signature {pkcs-1 4} ++ issuer "the certificate authority issuer name" ++ lastUpdate "UTC time" ++ nextUpdate "UTC time" ++ revokedCertificate { ++ -- the first entry ++ userCertificate "certificate serial number" ++ revocationData "UTC time" ++ .... ++ -- last entry ++ userCertificate "certificate serial number" ++ revocationData "UTC time" ++ } ++ } ++ pkcsCertRepEnvelope EnvelopedData ::= { ++ version 0 ++ recipientInfo { ++ version 0 ++ issuerAndSerialNumber { ++ issuer "the requester's issuer name" ++ serialNumber "the requester certificate serial number" ++ } ++ keyEncryptionAlgorithm {pkcs-1 1} ++ encryptedKey "content-encrypt key encrypted by requester's ++ public key " ++ } ++ encryptedContentInfo { ++ contentType {pkcs-7 1} -- data content ++ contentEncryptionAlgorithm "OID for DES encryption" ++ encryptedContent "encrypted pkcsCertRep using requester's ++ public key" ++ } ++ } ++ ++ ++ ++ ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 30] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ ++ pkcsCertRepSigned SignedData ::= { -- PKCS#7 ++ version 1 ++ digestAlgorithm {iso(1) member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ contentInfo { ++ contentType {pkcs-7 1} ++ content pkcsCertRepEnvelope ++ } ++ signerInfo { ++ version 1 ++ issuerAndSerialNumber { ++ issuer "the certificate authority issuer name" ++ serialNumber "the CA certificate's serial number" ++ } ++ digestAlgorithm {iso(1), member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ authenticateAttributes { ++ contentType {{pkcs-9 3} {pkcs-7 1}} ++ messageDigest {{pkcs-9 4} "an octet string"} ++ -- digest of pkcsCertRepEnvelope ++ messageType {{id-attribute messageType(2)} "CertRep"} ++ transaction-id {{id-attributes transId(7)} "printable ++ string"} ++ -- same transaction id as given in PKCSReq ++ pkiStatus {{id-attributes pkiStatus(3) "SUCCESS"} ++ recipientNonce{{id-attribute recipientNonce(6)}<16 bytes>} ++ senderNonce {{id-attribute senderNonce (5) 0x<16 bytes>} ++ } ++ digestEncryptionAlgorithm {pkcs-1 1} ++ encryptedDigest "encrypted digest of authenticatedAttributes ++ using CA private key" ++ } ++ } ++ ++ ++NOTE:The PKCS#7 EncryptedContent is specified as an octet string, but ++SCEP entities must also accept a sequence of octet strings as a valid ++alternate encoding. ++ ++This alternate encoding must be accepted wherever PKCS #7 Enveloped ++Data is specified in this document. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 31] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++5.5 Get Certificate Authority Certificate ++ ++Before any transaction begins, end entities have to get the CA (and ++possibly RA) certificate(s) first. Since the requester may have no CA ++certificates or CA public keys at all, this message can not be ++encrypted and the response must be authenticated by out-of-band means. ++These certs are obtained by means of an HTTP GET message. To get the ++CA certificate, the requester does a "HTTP GET" with a URL that ++identifies a CGI script on the server and an optional CA issuer ++identifier as the parameter to the CGI script. The response is either ++a single X.509 CA certificate ("CA mode"), or a PKCS7 message ++containing the CA certificate and RA certificates ("RA mode"). The ++client can determine which mode the CA operates in by which response ++it gets. Once the CA certificate is received by the requester, a ++fingerprint is generated using either the SHA-1 or the MD5 hash ++algorithm on the whole CA certificate. If the requester does not have ++a certificate path to a trusted CA certificate, this fingerprint may ++be used to verify the certificate, by some positive out-of-band means, ++such as a phone call. ++ ++5.5.1 GetCACert HTTP Message Format ++ "GET" CGI-PATH CGI-PROG "?operation=GetCACert" "&message=" CA-IDENT ++ where: ++ CGI-PATH defines the actual CGI path to invoke the CGI program ++ which parses the request. ++ CGI-PROG is set to be the string "pkiclient.exe" and this is ++ expected to be the program that the CA will use to handle the ++ SCEP transactions. ++ CA-IDENT is any string which is understood by the CA. ++ For example, it could be a domain name like ietf.org. ++ If a certificate authority has multiple CA certificates ++ this field can be used to distinguish which is required. ++ Otherwise it may be ignored. ++ ++5.5.2 Response ++ ++The response for GetCACert is different between the case where the CA ++directly communicated with the requester during the enrollment, and the ++case where a RA exists and the requester communicates with the RA ++during the enrollment. ++ ++5.5.2.1 CA Certificate Only Response ++ ++A binary X.509 CA certificate is sent back as a MIME object with a ++Content-Type of application/x-x509-ca-cert. ++ ++5.5.2.2 CA and RA Certificates Response ++ ++When an RA exists, both CA and RA certificates must be sent back in ++the response to the GetCACert request. The RA certificate(s) must be ++signed by the CA. A certificates-only PKCS#7 SignedData is used to ++carry the certificates to the requester, with a Content-Type of ++application/x-x509-ca-ra-cert. ++ ++ Liu/Madson/McGrew/Nourse [Page 32] ++ ++5.5.3 Get Next Certificate Authority Certificate ++ ++5.5.3.1 GetNextCACert HTTP Message Format ++ "GET" CGI-PATH CGI-PROG "?operation=GetNextCACert" "&message=" CA-IDENT ++ ++The response to this message is a PKCS#7 certificates-only message containing ++a CA certificate (and possibly RA certificates) to be used when the current CA ++certificate expires, signed with the current CA cert (or RA certificate, if ++the CA is in RA mode. Note that a PKCS#7 is returned even in CA mode. ++ ++5.5.3.2 GetCACaps HTTP Message Format ++ "GET" CGI-PATH CGI-PROG "?operation=GetCACaps" "&message=" CA-IDENT ++ ++This message requests capabilities from CA. The response is a list of ++text capabilities, as defined in Appendix F. Support for this message ++is optional, but if it is not supported, the client should assume that ++none of the capabilities in Appendix F are supported. ++ ++5.6 Get Certificate Authority Certificate Chain ++ ++GetCACertChain provides a way to get the entire certificate chain. ++ ++5.6.1 GetCACertChain HTTP Message Format ++ ++ "GET" CGI-SCRIPT "?" "operation=GetCACertChain" "&" "message" CA-IDENT ++ where CGI-SCRIPT and CA-IDENT are as described for GetCACert. ++ ++5.6.2 Response ++ ++The response for GetCACertChain is a certificates-only PKCS#7 SignedData ++to carry the certificates to the requester, with a Content-Type of ++application/x-x509-ca-ra-cert-chain. ++ ++5.6.3 Backwards Compatability ++ ++Versions of SCEP prior to revision 3 do not support GetCACertChain. ++Certificate Authorities written to these prior versions will not be ++able to process the message and may return an HTML error. ++ ++To avoid this, clients should send the GetCACert message first. If the ++returned certificate is self-signed or is signed by a Certificate ++Authority that is trusted by the client, then it is not necessary to ++send the GetCACertChain message and it should not be sent. ++ ++If a Certificate Authority is configured with a certificate that is ++not either self-signed or has a self-signed issuer, then it should ++support this message. In other words, it should be supported if the ++CA hierarchy is more than two-deep. ++ ++An old CA in a two-deep hierarchy might still get this message from ++a client if the client did not trust either that CA or its issuer. ++In that event, the certificate cannot be trusted anyway. In any case ++the CA must not crash or hang upon the receipt of the message and the ++client must be able to handle whatever error is returned by the CA, ++including an HTML error or an ungraceful disconnect. ++ ++ Liu/Madson/McGrew/Nourse [Page 33] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++The following is the ASN.1 definition of Cert-Only PKCS#7: ++ ++ certOnly SignedData ::= { ++ version 1 ++ digestAlgorithm {iso(1) member-body(2) US(840) rsadsi(113549) ++ digestAlgorithm(2) 5} ++ ++contentInfo { ++ contentType {pkcs-7 1} -- data content identifier ++ content -- NULL ++ } ++ certificates -- the RA and CA certificates. ++ } ++ ++ CARACerts PKIMessage ::= { -- special pki message sent in the clear ++ contentType {pkcs-7 2} ++ content certOnly ++ } ++ ++ ++6.0 Security Considerations ++ ++This entire document is about security. Common security considerations ++such as keeping private keys truly private and using adequate lengths ++for symmetric and asymmetric keys must be followed in order to maintain ++the security of this protocol. ++ ++ ++7.0 Intellectual Property ++ ++This protcol includes the optional use of Certificate Revocation List ++Distribution Point (CRLDP) technology, which is a patented technology ++of Entrust Technologies, Inc. (Method for Efficient Management of ++Certificate Revocation Lists and Update Information (U.S. Patent ++5,699,431)). Please contact Entrust Technologies, Inc. ++(www.entrust.com) for more information on licensing CRLDP technology. ++ ++ ++8.0 References ++ ++[PKCS7] Kaliski, B., "PKCS #7: Cryptographic Message Syntax Version ++1.5", RFC 2315, March 1998. ++ ++[PKCS10] Kaliski, B., "PKCS #10: Certification Request Syntax Version ++1.5", RFC 2314, March 1998. ++ ++[RFC2459] Housley, R., ec. al., "Internet X.509 Public Key ++Infrastructure Certificate and CRL Profile", RFC 2459, January 1999. ++ ++ ++ ++ ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 34] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++Appendix A: Cisco Requester Subject Name Definition ++ ++The ip address and the FQDN of a SCEP client should be included in the ++V3 extension subjectAltName. When the subjectAltName extension attribute ++is present, both the subjectAltName fields and the subjectName field could ++have the IP address and the FQDN information. ++ ++When the X.500 directory is used by the CA to define the name space, the ++subject name defined above become a RDN which is part of DN binded to ++the requester's public key in the certificate. ++ ++ ++A sample of DN assigned by Entrust CA is given below (assume the same ++ciscoRouterAlice is used as the requester defined subject name): ++ ++ OU = InteropTesting, O = Entrust Technologies, C = CA ++ RDN = {"alice.cisco.com", "172.21.114.67", "22334455"} ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 35] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++Appendix B: IPSEC Client Enrollment Certificate Request ++ ++The following is the certificate enrollment request (PKCS#10) as created ++by Cisco VPN Client: ++ ++-----END NEW CERTIFICATE REQUEST----- ++ 0 30 439: SEQUENCE { ++ 4 30 288: SEQUENCE { ++ 8 02 1: INTEGER 0 ++ 11 30 57: SEQUENCE { ++ 13 31 55: SET { ++ 15 30 53: SEQUENCE { ++ 17 06 3: OBJECT IDENTIFIER commonName (2 5 4 3) ++ 22 13 46: PrintableString ++ : 'For Xiaoyi, IPSEC attrs in alternate name ++ extn' ++ : } ++ : } ++ : } ++ 70 30 158: SEQUENCE { ++ 73 30 13: SEQUENCE { ++ 75 06 9: OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 ++ 1 1) ++ 86 05 0: NULL ++ : } ++ 88 03 140: BIT STRING 0 unused bits ++ : 30 81 88 02 81 80 73 DB 1D D5 65 AA EF C7 D4 8E ++ : AA 6E EB 46 AC 91 2A 0F 50 51 17 AD 50 A2 2A F2 ++ : CE BE F1 E4 22 8C D7 61 A1 6C 87 61 62 92 CB A6 ++ : 80 EA B4 0F 09 9D 18 5F 39 A3 02 0E DB 38 4C E4 ++ : 8A 63 2E 72 8B DC BE 9E ED 6C 1A 47 DE 13 1B 0F ++ : 83 29 4D 3E 08 86 FF 08 2B 43 09 EF 67 A7 6B EA ++ : 77 62 30 35 4D A9 0F 0F DF CC 44 F5 4D 2C 2E 19 ++ : E8 63 94 AC 84 A4 D0 01 E1 E3 97 16 CD 86 64 18 ++ : [ Another 11 bytes skipped ] ++ : } ++ 231 A0 63: [0] { ++ 233 30 61: SEQUENCE { ++ 235 06 9: OBJECT IDENTIFIER extensionReq (1 2 840 113549 1 9 ++ 14) ++ 246 31 48: SET { ++ 248 30 46: SEQUENCE { ++ 250 30 44: SEQUENCE { ++ 252 06 3: OBJECT IDENTIFIER subjectAltName (2 5 29 17) ++ 257 04 37: OCTET STRING ++ 30 23 87 04 01 02 03 04 81 0D 65 6D 61 69 ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 36] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ 6C 40 69 72 65 2E 63 6F 6D 82 0C 66 71 64 ++ 6E 2E 69 72 65 2E 63 6F 6D ++ : } ++ : } ++ : } ++ : } ++ : } ++ : } ++ ++ 296 30 13: SEQUENCE { ++ 298 06 9: OBJECT IDENTIFIER md5withRSAEncryption (1 2 840 113549 ++ 1 1 4) ++ 309 05 0: NULL ++ : } ++ 311 03 129: BIT STRING 0 unused bits ++ : 19 60 55 45 7F 72 FD 4E E5 3F D2 66 B0 77 13 9A ++ : 87 86 75 6A E1 36 C6 B6 21 71 68 BD 96 F0 B4 60 ++ : 95 8F 12 F1 65 33 16 FD 46 8A 63 19 90 40 B4 B7 ++ : 2C B5 AC 63 17 50 28 F0 CD A4 F0 00 4E D2 DE 6D ++ : C3 4F F5 CB 03 4D C8 D8 31 5A 7C 01 47 D2 2B 91 ++ : B5 48 55 C8 A7 0B DD 45 D3 4A 8D 94 04 3A 6C B0 ++ : A7 1D 64 74 AB 8A F7 FF 82 C7 22 0A 2A 95 FB 24 ++ : 88 AA B6 27 83 C1 EC 5E A0 BA 0C BA 2E 6D 50 C7 ++ : } ++ ++ ++Appendix C: Private OID Definitions ++ ++The OIDs used in defining pkiStatus are VeriSign self-maintained ++OIDs. Please note, work is in progress to replace the VeriSign owned ++object identifiers with the standard object identifiers. Once the ++standarlization is completed, this documentation will be updated. ++ ++id-VeriSign OBJECT_IDENTIFIER ::= {2 16 US(840) 1 VeriSign(113733)} ++id-pki OBJECT_IDENTIFIER ::= {id-VeriSign pki(1)} ++id-attributes OBJECT_IDENTIFIER ::= {id-pki attributes(9)} ++id-messageType OBJECT_IDENTIFIER ::= {id-attributes messageType(2)} ++id-pkiStatus OBJECT_IDENTIFIER ::= {id-attributes pkiStatus(3)} ++id-failInfo OBJECT_IDENTIFIER ::= {id-attributes failInfo(4)} ++id-senderNonce OBJECT_IDENTIFIER ::= {id-attributes senderNonce(5)} ++id-recipientNonce OBJECT_IDENTIFIER ::= {id-attributes recipientNonce(6)} ++id-transId OBJECT_IDENTIFIER ::= {id-attributes transId(7)} ++id-extensionReq OBJECT_IDENTIFIER ::= {id-attributes extensionReq(8)} ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 37] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ Appendix D: CRL Query by means of LDAP ++ ++ In order to retrieve the CRL by means of LDAP, the client needs to know ++ where in the directory it is stored. The certificate must contain a ++ CRL Distribution Point extension encoded as a DN or as an LDAP URI. ++ ++For example, the certificate issued by Entrust VPN contains ++the following DN as the CRL distribution point: ++ ++ ++ ++CN = CRL1, O = cisco, C = US. ++ ++ The asn.1 encoding of this distribution point is: ++ ++ 30 2C 31 0B 30 09 06 03 55 04 06 13 02 55 53 31 0E 30 0C 06 ++ 03 55 04 0A 13 05 63 69 73 63 6F 31 0D 30 0B 06 03 55 04 03 ++ 13 04 43 52 4C 31 ++ ++ ++The ldap form would be: ++ ++ldap://servername/CN=CRL1,O=cisco,C=US ++ ++ ++ ++Appendix E: SCEP State Transitions ++ ++SCEP state transitions are based on transaction identifier. The design ++goal is to ensure the synchronization between the CA and the requester ++under various error situations. ++ ++ ++An identity is defined by the combination of FQDN, the IP address and ++the client serial number. FQDN is the required name attribute. It is ++important to notice that, a client named as Alice.cisco.com is different ++from the client named as Alice.cisco.com plus IPAddress 117.96.1.219. ++ ++Each enrollment transaction is uniquely associated with a transaction ++identifier. Because the enrollment transaction could be interrupted by ++various errors, including network connection errors or client reboot, ++the SCEP client generates a transaction identifier by calculating a ++hash on the public key value for which the enrollment is requested. This ++retains the same transaction identifier throughout the enrollment ++transaction, even if the client has rebooted or timed out, and issues a ++new enrollment request for the same key pair. It also provides the way ++for the CA to uniquely identify a transaction in its database. At the ++requester side, it generates a transaction identifier which is included ++in PKCSReq. If the CA returns a response of PENDING, the requester ++will poll by periodically sending out GetCertInitial with the same ++transaction identifier until either a response other than PENDING is ++obtained, or the configured maximum time has elapsed. ++ ++If the client times out or the client reboots, the client administrator ++will start another enrollment transaction with the same key pair. The ++second enrollment will have the transaction idenifier. At the server ++side, instead of accepting the PKCSReq as a new enrollment request, it ++should respond as if another GetCertInitial message had been sent with ++that transaction ID. In another word, the second PKCSReq should be ++taken as a resynchronization message to allow the enrollment resume as ++the same transaction. ++ ++It is important to keep the transaction id unique since SCEP requires the ++same policy and same identity be applied to the same subject name and ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 38] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++key pair binding. In the current implementation, an SCEP client can ++only assume one identity. At any time, only one key pair, with a given ++key usage, can be associated with the same identity. ++ ++The following gives several examples of client to CA transactions. ++ ++Client actions are indicated in the left column, CA actions are ++indicated in the right column. A blank action signifies that no message ++was received. Note that these examples assume that the CA enforces the ++certificate-name uniqueness property defined in Section 2.1.1.1. ++ ++The first transaction, for example, would read like this: ++ "Client Sends PKCSReq message with transaction ID 1 to the ++ CA. The CA signs the certificate and constructs a CertRep Message ++ containing the signed certificate with a transaction ID 1. The client ++ receives the message and installs the cert locally." ++ ++Successful Enrollment Case: no manual authentication ++PKCSReq (1) ----------> CA Signs Cert ++Client Installs Cert <---------- CertRep (1) SIGNED CERT ++ ++ ++ ++Successful Enrollment Case: manual authentication required ++PKCSReq (10) ----------> Cert Request goes into Queue ++Client Polls <---------- CertRep (10) PENDING ++GetCertInitial (10) ----------> Still pending ++Client Polls <---------- CertRep (10) PENDING ++GetCertInitial (10) ----------> Still pending ++Client Polls <---------- CertRep (10) PENDING ++GetCertInitial (10) ----------> Still pending ++Client Polls <---------- CertRep (10) PENDING ++GetCertInitial (10) ----------> Cert has been signed ++Client Installs Cert <---------- CertRep (10) SIGNED CERT ++ ++ ++ ++Resync Case - CA Receive and Signs PKCSReq, Client Did not receive ++CertRep: ++ ++PKCSReq (3) ----------> Cert Request goes into queue ++ <---------- CertRep (3) PENDING ++GetCertInitial (3) ----------> ++ <---------- CertRep (3) PENDING ++GetCertInitial (3) -----------> ++ <----------- CA signed Cert and sent back ++ CertRep(3) ++(Time Out) ++PKCSReq (3) ----------> Cert already signed, sent back to ++ client ++Client Installs Cert <---------- CertRep (3) SIGNED CERT ++ ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 39] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++ ++Case when NVRAM is lost and client has to generate a new key pair, there ++is no change of name information: ++ ++PKCSReq (4) ----------> CA Signs Cert ++Client Installs Cert <---------- CertRep (4) SIGNED CERT ++(Client looses Cert) ++PKCSReq (5) ----------> There is already a valid cert with ++ this DN. ++Client Admin Revokes <---------- CertRep (5) OVERLAPPING CERT ERROR ++PKCSReq (5) ----------> CA Signs Cert ++Client Installs Cert <---------- CertRep (5) SIGNED CERT ++ ++ ++Case when client admin resync the enrollment using a different PKCS#10: ++PKCSReq (6) ----------> CA Signs Cert ++ <---------- CertRep (6) SIGNED CERT ++(Client timeout and admin starts another enrollment with a different ++ PKCS#10, but the same transaction id) ++PKCSReq (6) with different PKCS#10 ++ ----------> There is already a valid cert with ++ this entity (by checking FQDN). ++ <---------- CertRep (6) INVALID PKCS#10 CERT ++ ERROR ++Client admin either revokes the existing cert ++or corrects the error by enrolling with ++the same PKCS#10 as the first PKCSReq(6) ++PKCSReq (6) ----------> CA find the existing Cert ++Client Installs Cert <---------- CertRep (6) SIGNED CERT ++ ++ ++Resync case when server is slow in response: ++PKCSReq (13) ----------> Cert Request goes into Queue ++ <---------- CertRep (13) PENDING ++GetCertInitial ----------> Still pending ++ <---------- CertRep (13) PENDING ++GetCertInitial ----------> Still pending ++ <---------- CertRep (13) PENDING ++GetCertInitial ----------> Still pending ++ <---------- CertRep (13) PENDING ++GetCertInitial ----------> Still pending ++(TimeOut) <---------- CertRep (13) PENDING ++* Case 1 ++PKCSReq (13) ----------> Still pending ++Client polls <---------- CertRep (13) PENDING ++CertCertInitial ----------> Cert has been signed ++Client Installs Cert <---------- CertRep (13) SIGNED CERT ++* Case 2 ++PKCSReq (13) ----------> Cert has been signed ++Client Installs Cert <---------- CertRep (13) SIGNED CERT ++ ++ ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 40] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++Appendix F. CA Capabilities ++ ++The response for a GetCACaps message is a list of CA capabilities, in ++plain text, separated by characters, as follows (quotation marks ++are NOT sent): ++ ++Keyword Description ++ ++"GetNextCACert" CA Supports the GetNextCACert message. ++"POSTPKIOperation" PKIOPeration messages may be sent via HTTP POST. ++"SHA-1" CA Supports the SHA-1 hashing algorithm in ++ signatures and fingerprints. If present, the ++ client SHOULD use SHA-1. If absent, the client ++ MUST use MD5 to maintain backward compatability. ++"Renewal" Clients may use current certificate and key to ++ authenticate an enrollment request for a new ++ certificate. ++ ++A client must be able to accept and ignore any unknown keywords that ++might be sent back by a CA that implements a future version of SCEP. ++ ++Example: ++ ++GET /cgi-bin/pkiclient.exe?operation=GetCACaps&message=myca ++ ++returns: ++ ++GetNextCACert ++POSTPKIOperation ++ ++This means that the CA supports the GetNextCACert message and allows ++PKIOperation messages (PKCSreq, GetCert, GetCertInitial...) to be sent ++using HTTP POST. ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 41] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++Appendix G. Certificate Renewal and CA Key Rollover ++ ++To renew a client certificate, use the PKCSreq message and sign it with ++the existing client certificate instead of a self-signed certificate. ++ ++To obtain the new CA certificate prior to the expiration of the current ++one, use the GetNextCACert message if the CA supports it. ++ ++To obtain a new client certificate signed by the new CA certificate, ++use the new CA or RA certificate in the message envelope. ++ ++ ++Example: ++ ++GetNextCACert ----------> ++ <---------- CertRep (3) New CA certificate ++ ++PKCSReq* (1) ----------> CA Signs certificate with NEW key ++Client Stores Cert <---------- CertRep (3) Certificate issued ++for installation when from NEW CA certificate and keypair. ++existing cert expires. ++ ++ ++*enveloped for new CA or RA cert and keypair. The CA will use the ++envelope to determine which key and certificate to use to issue the ++client certificate. ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 42] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++Appendix H. PKIOperation via HTTP POST Message ++ ++If the remote CA supports it, any of the PKCS#7-encoded SCEP messages ++may be sent via HTTP POST instead of HTTP GET. This is allowed for ++any SCEP message except GetCACert, GetCACertChain, GetNextCACert, ++or GetCACaps. In this form of the message, Base 64 encoding is not ++used. ++ ++POST /cgi-bin/pkiclient.exe?operation=PKIOperation ++ ++ ++The client can verify that the CA supports SCEP messages via POST by ++looking for the "POSTPKIOperation" capability (See Appendix F). ++ ++ ++ ++ ++ ++ ++ Liu/Madson/McGrew/Nourse [Page 43] ++ ++Cisco Systems' Simple Certificate Enrollment Protocol Feb 2005 ++ ++Appendix Y. Author Contact Information ++ ++Xiaoyi Liu Cheryl Madson ++Cisco Cisco ++510 McCarthy Drive 510 McCarthy Drive ++Milpitas, CA Milpitas, CA. ++xliu@cisco.com cmadson@cisco.com ++ ++ ++David McGrew Andrew Nourse ++Cisco Cisco ++170 West Tasman Drive 510 McCarthy Drive ++San Jose, CA 94134 Milpitas, CA. ++mcgrew@cisco.com nourse@cisco.com ++ ++ ++ ++ ++Appendix Z. Copyright Section ++ ++Copyright (C) The Internet Society (2005). This document is subject ++to the rights, licenses and restrictions contained in BCP 78, and ++except as set forth therein, the authors retain all their rights. ++ ++This document and the information contained herein are provided on an ++"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS ++OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ++ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, ++INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE ++INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED ++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. ++ ++ ++ ++ ++This draft expires 11 Aug 2005 ++ ++[End of draft-nourse-scep-11.txt] ++ +diff -uN sscep/fileutils.c sscep-ng2/fileutils.c +--- sscep/fileutils.c 2003-04-15 12:53:45.000000000 +0200 ++++ sscep-ng2/fileutils.c 2006-04-28 10:03:24.000000000 +0200 +@@ -55,8 +55,11 @@ + PKCS7 *p7; + STACK_OF(X509) *certs; + X509 *cert = NULL; ++ ASN1_BIT_STRING *cert_pubkey = NULL; + FILE *fp; + int i; ++ ASN1_BIT_STRING *request_pubkey = ++ request->req_info->pubkey->public_key; + + localcert = NULL; + +@@ -66,29 +69,44 @@ + + /* Find cert */ + for (i = 0; i < sk_X509_num(certs); i++) { +- char buffer[1024]; +- + cert = sk_X509_value(certs, i); ++ cert_pubkey = X509_get_X509_PUBKEY(cert)->public_key; ++#define fu_print_name(n) \ ++ X509_NAME_print_ex_fp(stdout,(n),0,XN_FLAG_RFC2253|ASN1_STRFLGS_SHOW_TYPE) + if (v_flag) { +- printf("%s: found certificate with\n" +- " subject: %s\n", pname, +- X509_NAME_oneline(X509_get_subject_name(cert), +- buffer, sizeof(buffer))); +- printf(" issuer: %s\n", +- X509_NAME_oneline(X509_get_issuer_name(cert), +- buffer, sizeof(buffer))); ++ printf("%s: found certificate with\n subject: ", pname); ++ fu_print_name(X509_get_subject_name(cert)); ++ printf("\n issuer: "); ++ fu_print_name(X509_get_issuer_name(cert)); ++ printf("\n"); + } +- /* The subject has to match that of our request */ +- if (!X509_NAME_cmp(X509_get_subject_name(cert), ++ /* The public keys of the request and certificate must match */ ++ if (M_ASN1_BIT_STRING_cmp(request_pubkey,cert_pubkey) != 0) { ++ if (v_flag) ++ printf(" public keys of request and certificate don't match\n"); ++ continue; ++ } ++ /* The subject has to match that of our request, ++ if the "Compare subject DN" flag is set */ ++ if (C_flag && X509_NAME_cmp(X509_get_subject_name(cert), + X509_REQ_get_subject_name(request))) { +- +- /* The subject cannot be the issuer (selfsigned) */ +- if (X509_NAME_cmp(X509_get_subject_name(cert), +- X509_get_issuer_name(cert))) { +- localcert = cert; +- break; ++ if (v_flag) { ++ printf(" certificate subject names doesn't match request subject name:\n "); ++ fu_print_name(X509_REQ_get_subject_name(request)); ++ printf("\n"); + } +- } ++ continue; ++ } ++#undef fu_print_name ++ /* The subject cannot be the issuer (selfsigned) */ ++ if (!X509_NAME_cmp(X509_get_subject_name(cert), ++ X509_get_issuer_name(cert))) { ++ if (v_flag) ++ printf(" certificate is self signed\n"); ++ continue; ++ } ++ localcert = cert; ++ break; + } + if (localcert == NULL) { + fprintf(stderr, "%s: cannot find requested certificate\n", +@@ -320,34 +338,36 @@ + /* Read local certificate (GetCert and GetCrl) */ + + void +-read_local_cert(void) { +- if (!l_flag || !(localfile = fopen(l_char, "r"))) { +- fprintf(stderr, "%s: cannot open local cert file\n", pname); ++read_cert(X509** cert, char* filename) { ++ FILE *file; ++ if (!(file = fopen(filename, "r"))) { ++ fprintf(stderr, "%s: cannot open cert file %s\n", pname, filename); + exit (SCEP_PKISTATUS_FILE); + } +- if (!PEM_read_X509(localfile, &localcert, NULL, NULL)) { +- fprintf(stderr, "%s: error while reading local cert\n", pname); ++ if (!PEM_read_X509(file, cert, NULL, NULL)) { ++ fprintf(stderr, "%s: error while reading cert %s\n", pname, filename); + ERR_print_errors_fp(stderr); + exit (SCEP_PKISTATUS_FILE); + } +- fclose(localfile); ++ fclose(file); + } + + /* Read private key */ + + void +-read_key(void) { ++read_key(EVP_PKEY** key, char* filename) { ++ FILE *file; + /* Read private key file */ +- if (!k_flag || !(keyfile = fopen(k_char, "r"))) { +- fprintf(stderr, "%s: cannot open private key file\n", pname); ++ if (!(file = fopen(filename, "r"))) { ++ fprintf(stderr, "%s: cannot open private key file %s\n", pname, filename); + exit (SCEP_PKISTATUS_FILE); + } +- if (!PEM_read_PrivateKey(keyfile, &rsa, NULL, NULL)) { +- fprintf(stderr, "%s: error while reading private key\n", pname); ++ if (!PEM_read_PrivateKey(file, key, NULL, NULL)) { ++ fprintf(stderr, "%s: error while reading private key %s\n", pname, filename); + ERR_print_errors_fp(stderr); + exit (SCEP_PKISTATUS_FILE); + } +- fclose(keyfile); ++ fclose(file); + } + + /* Read PKCS#10 request */ +diff -uN sscep/init.c sscep-ng2/init.c +--- sscep/init.c 2003-01-31 10:07:16.000000000 +0100 ++++ sscep-ng2/init.c 2006-04-28 10:11:40.000000000 +0200 +@@ -61,6 +61,9 @@ + if (!(i_char = strdup(str2))) + error_memory(); + } ++ } else if (!strncmp(str1, "CheckSubjectName", 16)) { ++ if (!strncmp(str2, "yes", 3) && !C_flag) ++ C_flag = 1; + } else if (!strncmp(str1, "CertReqFile", 11)) { + if (!r_flag) { + r_flag = 1; +@@ -114,6 +117,12 @@ + if (!(l_char = strdup(str2))) + error_memory(); + } ++ } else if (!strncmp(str1, "SignCertFile", 12)) { ++ if (!O_flag) { ++ O_flag = 1; ++ if (!(O_char = strdup(str2))) ++ error_memory(); ++ } + } else if (!strncmp(str1, "MaxPollCount", 12)) { + if (!n_flag) { + n_flag = 1; +@@ -130,6 +139,12 @@ + if (!(k_char = strdup(str2))) + error_memory(); + } ++ } else if (!strncmp(str1, "SignKeyFile", 11)) { ++ if (!K_flag) { ++ K_flag = 1; ++ if (!(K_char = strdup(str2))) ++ error_memory(); ++ } + } else if (!strncmp(str1, "SelfSignedFile", 15)) { + if (!L_flag) { + L_flag = 1; +diff -uN sscep/pkcs7.c sscep-ng2/pkcs7.c +--- sscep/pkcs7.c 2003-02-10 06:04:48.000000000 +0100 ++++ sscep-ng2/pkcs7.c 2006-04-26 13:40:34.000000000 +0200 +@@ -28,7 +28,8 @@ + PKCS7 *p7enc; + PKCS7_SIGNER_INFO *si; + STACK_OF(X509_ATTRIBUTE) *attributes; +- X509 *signer = NULL; ++ X509 *signercert = NULL; ++ EVP_PKEY *signerkey = NULL; + + /* Create a new sender nonce for all messages + * XXXXXXXXXXXXXX should it be per transaction? */ +@@ -47,7 +48,8 @@ + s->request_type_str = SCEP_REQUEST_PKCSREQ_STR; + + /* Signer cert */ +- signer = s->selfsigned; ++ signercert = s->signercert; ++ signerkey = s->signerkey; + + /* Create inner PKCS#7 */ + if (v_flag) +@@ -71,7 +73,8 @@ + s->request_type_str = SCEP_REQUEST_GETCERTINIT_STR; + + /* Signer cert */ +- signer = s->selfsigned; ++ signercert = s->signercert; ++ signerkey = s->signerkey; + + /* Create inner PKCS#7 */ + if (v_flag) +@@ -95,7 +98,8 @@ + s->request_type_str = SCEP_REQUEST_GETCERT_STR; + + /* Signer cert */ +- signer = localcert; ++ signercert = localcert; ++ signerkey = rsa; + + /* Read data in memory bio */ + databio = BIO_new(BIO_s_mem()); +@@ -115,7 +119,8 @@ + s->request_type_str = SCEP_REQUEST_GETCRL_STR; + + /* Signer cert */ +- signer = localcert; ++ signercert = localcert; ++ signerkey = rsa; + + /* Read data in memory bio */ + databio = BIO_new(BIO_s_mem()); +@@ -217,9 +222,9 @@ + } + + /* Add signer certificate and signature */ +- PKCS7_add_certificate(s->request_p7, signer); ++ PKCS7_add_certificate(s->request_p7, signercert); + if ((si = PKCS7_add_signature(s->request_p7, +- signer, rsa, sig_alg)) == NULL) { ++ signercert, signerkey, sig_alg)) == NULL) { + fprintf(stderr, "%s: error adding PKCS#7 signature\n", pname); + ERR_print_errors_fp(stderr); + exit (SCEP_PKISTATUS_P7); +@@ -317,7 +322,8 @@ + STACK_OF(X509_ATTRIBUTE) *attribs; + char *p; + unsigned char buffer[1024]; +- X509 *recipient; ++ X509 *recipientcert; ++ EVP_PKEY *recipientkey; + + /* Create new memory BIO for outer PKCS#7 */ + memorybio = BIO_new(BIO_s_mem()); +@@ -547,10 +553,14 @@ + + /* Decrypt the inner PKCS#7 */ + if ((s->request_type == SCEP_REQUEST_PKCSREQ) || +- (s->request_type == SCEP_REQUEST_GETCERTINIT)) +- recipient = s->selfsigned; +- else +- recipient = localcert; ++ (s->request_type == SCEP_REQUEST_GETCERTINIT)) { ++ recipientcert = s->signercert; ++ recipientkey = s->signerkey; ++ } ++ else { ++ recipientcert = localcert; ++ recipientkey = rsa; ++ } + if (v_flag) + printf("%s: reading inner PKCS#7\n",pname); + p7enc = d2i_PKCS7_bio(outbio, NULL); +@@ -568,7 +578,7 @@ + outbio = BIO_new(BIO_s_mem()); + if (v_flag) + printf("%s: decrypting inner PKCS#7\n",pname); +- if (PKCS7_decrypt(p7enc, rsa, recipient, outbio, 0) == 0) { ++ if (PKCS7_decrypt(p7enc, recipientkey, recipientcert, outbio, 0) == 0) { + fprintf(stderr, "%s: error decrypting inner PKCS#7\n", pname); + ERR_print_errors_fp(stderr); + exit (SCEP_PKISTATUS_P7); +diff -uN sscep/sceputils.c sscep-ng2/sceputils.c +--- sscep/sceputils.c 2003-02-09 14:18:23.000000000 +0100 ++++ sscep-ng2/sceputils.c 2006-04-25 16:27:03.000000000 +0200 +@@ -156,7 +156,8 @@ + } + + /* Copy the pointer and return */ +- s->selfsigned = cert; ++ s->signercert = cert; ++ s->signerkey = rsa; + return (0); + } + +diff -uN sscep/sscep.c sscep-ng2/sscep.c +--- sscep/sscep.c 2003-04-17 07:47:04.000000000 +0200 ++++ sscep-ng2/sscep.c 2006-04-28 11:06:16.000000000 +0200 +@@ -53,12 +53,15 @@ + } + /* Skip first parameter and parse the rest of the command */ + optind++; +- while ((c = getopt(argc, argv, "c:de:E:f:F:i:k:l:L:n:p:r:Rs:S:t:T:u:vw:")) != -1) ++ while ((c = getopt(argc, argv, "c:Cde:E:f:F:i:k:K:l:L:n:O:p:r:Rs:S:t:T:u:vw:")) != -1) + switch(c) { + case 'c': + c_flag = 1; + c_char = optarg; + break; ++ case 'C': ++ C_flag = 1; ++ break; + case 'd': + d_flag = 1; + break; +@@ -86,6 +89,10 @@ + k_flag = 1; + k_char = optarg; + break; ++ case 'K': ++ K_flag = 1; ++ K_char = optarg; ++ break; + case 'l': + l_flag = 1; + l_char = optarg; +@@ -98,6 +105,10 @@ + n_flag = 1; + n_num = atoi(optarg); + break; ++ case 'O': ++ O_flag = 1; ++ O_char = optarg; ++ break; + case 'p': + p_flag = 1; + p_char = optarg; +@@ -137,6 +148,7 @@ + w_char = optarg; + break; + default: ++ printf("argv: %s\n", argv[optind]); + usage(); + } + argc -= optind; +@@ -402,15 +414,38 @@ + case SCEP_OPERATION_GETCERT: + case SCEP_OPERATION_GETCRL: + /* Read local certificate */ +- read_local_cert(); ++ if (!l_flag) { ++ fprintf(stderr, "%s: missing local cert (-l)\n", pname); ++ exit (SCEP_PKISTATUS_FILE); ++ } ++ read_cert(&localcert, l_char); + + case SCEP_OPERATION_ENROLL: + /* + * Read in CA cert, private key and certificate + * request in global variables. + */ +- read_ca_cert(); +- read_key(); ++ read_ca_cert(); ++ ++ if (!k_flag) { ++ fprintf(stderr, "%s: missing private key (-k)\n", pname); ++ exit (SCEP_PKISTATUS_FILE); ++ } ++ read_key(&rsa, k_char); ++ ++ if ((K_flag && !O_flag) || (!K_flag && O_flag)) { ++ fprintf(stderr, "%s: -O also requires -K (and vice-versa)\n", pname); ++ exit (SCEP_PKISTATUS_FILE); ++ } ++ ++ if (K_flag) { ++ read_key(&renewal_key, K_char); ++ } ++ ++ if (O_flag) { ++ read_cert(&renewal_cert, O_char); ++ } ++ + if (operation_flag == SCEP_OPERATION_ENROLL) + read_request(); + +@@ -426,7 +461,14 @@ + if (v_flag) + fprintf(stdout, "%s: generating selfsigned " + "certificate\n", pname); +- new_selfsigned(&scep_t); ++ ++ if (! O_flag) ++ new_selfsigned(&scep_t); ++ else { ++ /* Use existing certificate */ ++ scep_t.signercert = renewal_cert; ++ scep_t.signerkey = renewal_key; ++ } + + /* Write the selfsigned certificate if requested */ + if (L_flag) { +@@ -436,7 +478,7 @@ + "file for writing\n", pname); + exit (SCEP_PKISTATUS_ERROR); + } +- if (PEM_write_X509(fp,scep_t.selfsigned) != 1) { ++ if (PEM_write_X509(fp,scep_t.signercert) != 1) { + fprintf(stderr, "%s: error while " + "writing certificate file\n", pname); + ERR_print_errors_fp(stderr); +@@ -643,7 +685,8 @@ + + void + usage() { +- fprintf(stdout, "\nsscep version %s\n\n" , VERSION); ++ fprintf(stdout, "\nsscep version %s using %s\n\n" , ++ VERSION,SSLeay_version(SSLEAY_VERSION)); + fprintf(stdout, "Usage: %s OPERATION [OPTIONS]\n" + "\nAvailable OPERATIONs are\n" + " getca Get CA/RA certificate(s)\n" +@@ -665,6 +708,8 @@ + "\nOPTIONS for OPERATION enroll are\n" + " -k Private key file\n" + " -r Certificate request file\n" ++ " -K Signature private key file, use with -O\n" ++ " -O Signature certificate (used instead of self-signed)\n" + " -l Write enrolled certificate in file\n" + " -e Use different CA cert for encryption\n" + " -L Write selfsigned certificate in file\n" +@@ -672,6 +717,8 @@ + " -T Max polling time in seconds\n" + " -n Max number of GetCertInitial requests\n" + " -R Resume interrupted enrollment\n" ++ " -C Check subject DN in the certificate return by the\n" ++ " CA (default is to match on the public key only)\n" + "\nOPTIONS for OPERATION getcert are\n" + " -k Private key file\n" + " -l Local certificate file\n" +diff -uN sscep/sscep.h sscep-ng2/sscep.h +--- sscep/sscep.h 2003-04-17 07:50:04.000000000 +0200 ++++ sscep-ng2/sscep.h 2006-04-28 10:46:49.000000000 +0200 +@@ -36,10 +36,9 @@ + #include + #include + +- + /* Global defines */ + +-#define VERSION "20030417" ++#define VERSION "20060428" + + /* SCEP operations */ + int operation_flag; +@@ -128,13 +127,13 @@ + X509 *encert; + X509 *localcert; + X509 *othercert; ++X509 *renewal_cert; + X509_REQ *request; + EVP_PKEY *rsa; ++EVP_PKEY *renewal_key; + X509_CRL *crl; + FILE *cafile; + FILE *reqfile; +-FILE *keyfile; +-FILE *localfile; + FILE *otherfile; + FILE *crlfile; + +@@ -207,7 +206,9 @@ + int recipient_nonce_len; + + /* Certificates */ +- X509 *selfsigned; ++ X509 *signercert; ++ EVP_PKEY *signerkey; ++ + EVP_PKEY *pkey; + + /* Request */ +@@ -251,13 +252,13 @@ + int init_scep(void); + + /* Read RSA private key file */ +-void read_key(void); ++void read_key(EVP_PKEY** key, char* filename); + + /* Read CA certificate file */ + void read_ca_cert(void); + + /* Read local certificate file */ +-void read_local_cert(void); ++void read_cert(X509** cert, char* filename); + + /* Read certificate request and private key */ + void read_request(void);