class RubyScep::PkiMessage

Constants

OID_CONTENT_TYPE
OID_DATA
OID_DES_ALGO
OID_ENVELOPED_DATA
OID_EXTENSION_REQUEST
OID_FAIL_INFO
OID_HASH_ALGO_IDENTIFIER
OID_MESSAGE_DIGEST
OID_MESSAGE_TYPE

get OID corresponding name oid-info.com/get/ oid> get possible values for a given OID in the CMS RFC www.ietf.org/rfc/rfc3369.txt

OID_PKI_STATUS
OID_RECIPIENT_NOUNCE
OID_RSA_ENCRYPTION
OID_SENDER_NONCE
OID_SIGNED_DATA
OID_SIGNING_TIME
OID_TRANSACTION_ID
SCEP_FAIL_INFOS
SCEP_MESSAGE_TYPES

complete list of possible SCEP values can be found in CISCO's documentation www.cisco.com/c/en/us/support/docs/security-vpn/public-key-infrastructure-pki/116167-technote-scep-00.html

SCEP_PKI_STATUSES

Attributes

challenge_password[RW]
device_certificate[RW]
enrollment_response[RW]
p7[RW]

Public Class Methods

new(asn1, p7) click to toggle source
# File lib/ruby_scep/pki_message.rb, line 35
def initialize(asn1, p7)
  signed_attributes = retrieve_signed_attributes(asn1)
  @message_type = SCEP_MESSAGE_TYPES.key(signed_attributes[OID_MESSAGE_TYPE].to_i)
  @transaction_id = signed_attributes[OID_TRANSACTION_ID]
  @sender_nonce = signed_attributes[OID_SENDER_NONCE]
  @p7 = p7
end

Public Instance Methods

build_enrollment_response!(csr) click to toggle source

We are building a SCEP Secure Message Object with a valid PKCS7 structure, as referenced

in https://tools.ietf.org/html/draft-nourse-scep-23#section-3

To see a graphical representation of the final PKCS7 structure, go to

https://www.cisco.com/c/dam/en/us/support/docs/security-vpn/public-key-infrastructure-pki/116167-technote-scep-00-01.jpeg

Structure:

1. degenerate
  a. version
  b. x509
2. enveloped data
  a. version
  b. list of recepients
  c. encrypted data (aka 1. degenerate)
3. signed data
  a. version
  b. hashing algo
  c. signed (unencrypted) data (aka 2. enveloped data)
  d. ca certificate
  e. digital signature
# File lib/ruby_scep/pki_message.rb, line 61
def build_enrollment_response!(csr)
  extract_challenge_password!(csr)
  generate_device_certificate!(csr)
  degenerate_sequence = build_degenerate_sequence
  enveloped_data_sequence = build_enveloped_data_sequence(degenerate_sequence)
  @enrollment_response = build_signed_data_sequence(enveloped_data_sequence)
end

Private Instance Methods

build_degenerate_sequence() click to toggle source
# File lib/ruby_scep/pki_message.rb, line 96
def build_degenerate_sequence
  PkiMessage::Degenerate.new(@device_certificate).to_der
end
build_enveloped_data_sequence(degenerate_sequence) click to toggle source
# File lib/ruby_scep/pki_message.rb, line 100
def build_enveloped_data_sequence(degenerate_sequence)
  encrypted_payload, encryption_key, encryption_iv = encrypt_payload(degenerate_sequence)
  PkiMessage::EnvelopedData.new(@p7, encryption_key, encryption_iv, encrypted_payload).to_der
end
build_signed_data_sequence(enveloped_data_sequence) click to toggle source
# File lib/ruby_scep/pki_message.rb, line 115
def build_signed_data_sequence(enveloped_data_sequence)
  PkiMessage::SignedData.new(
    enveloped_data_sequence,
    RubyScep.configuration.ca,
    RubyScep.configuration.ca_key,
    @sender_nonce,
    @transaction_id
  ).to_der
end
encrypt_payload(der) click to toggle source
# File lib/ruby_scep/pki_message.rb, line 105
def encrypt_payload(der)
  des = OpenSSL::Cipher::Cipher.new('des-ede3-cbc')
  des.encrypt
  encryption_key = des.random_key
  encryption_iv = des.random_iv
  des.key = encryption_key
  des.iv = encryption_iv
  [des.update(der) + des.final, encryption_key, encryption_iv]
end
extract_challenge_password!(csr) click to toggle source
# File lib/ruby_scep/pki_message.rb, line 79
def extract_challenge_password!(csr)
  raw_attribute = csr.attributes.find { |a| a.oid == 'challengePassword' }
  if raw_attribute.nil?
    @challenge_password = nil
  else
    @challenge_password = raw_attribute.value.value.first.value
  end
end
generate_device_certificate!(csr) click to toggle source

Generates and sets the certificate the device will use to identify itself to the MDM server. The certificate will be embedded in the PKIMessage response to complete the SCEP process.

# File lib/ruby_scep/pki_message.rb, line 90
def generate_device_certificate!(csr)
  certificate = CertificateBuilder.build(csr)
  certificate.sign(RubyScep.configuration.ca_key, OpenSSL::Digest::SHA1.new)
  @device_certificate = certificate
end
retrieve_signed_attributes(asn1) click to toggle source
# File lib/ruby_scep/pki_message.rb, line 71
def retrieve_signed_attributes(asn1)
  # cheers AppBlade! https://github.com/AppBlade/TestHub/blob/master/app/controllers/scep_controller.rb#L92-L112
  raw_signed_attributes = asn1.value[1].value.first.value[4].first.value[3].value
  raw_signed_attributes.inject({}) do |hash, raw_signed_attribute|
    hash.merge(raw_signed_attribute.value.first.value => raw_signed_attribute.value.last.value.first.value)
  end
end