confium 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/Cargo.lock +105 -5
  4. data/Rakefile +7 -7
  5. data/confium.gemspec +28 -28
  6. data/ext/confium_native/Cargo.toml +1 -0
  7. data/ext/confium_native/extconf.rb +4 -4
  8. data/ext/confium_native/src/attributes.rs +1 -1
  9. data/ext/confium_native/src/audit.rs +1 -1
  10. data/ext/confium_native/src/composite.rs +1 -1
  11. data/ext/confium_native/src/deployment.rs +1 -1
  12. data/ext/confium_native/src/ers.rs +1 -1
  13. data/ext/confium_native/src/openpgp.rs +1 -1
  14. data/ext/confium_native/src/path.rs +1 -1
  15. data/ext/confium_native/src/pki.rs +1 -1
  16. data/ext/confium_native/src/tc.rs +2 -2
  17. data/ext/confium_native/src/transparency.rs +5 -3
  18. data/ext/confium_native/src/util.rs +5 -0
  19. data/lib/confium/audit.rb +5 -5
  20. data/lib/confium/cfm.rb +2 -1
  21. data/lib/confium/digest.rb +4 -2
  22. data/lib/confium/errors/coerce.rb +1 -3
  23. data/lib/confium/errors/crypto_error.rb +8 -6
  24. data/lib/confium/errors/index_error.rb +9 -7
  25. data/lib/confium/errors/not_found_error.rb +9 -7
  26. data/lib/confium/errors/parse_error.rb +9 -7
  27. data/lib/confium/errors/policy_violation_error.rb +9 -7
  28. data/lib/confium/errors/threshold_error.rb +9 -7
  29. data/lib/confium/errors/unresolved_signer_error.rb +8 -6
  30. data/lib/confium/errors/validation_error.rb +10 -8
  31. data/lib/confium/errors/verification_error.rb +9 -7
  32. data/lib/confium/errors.rb +1 -1
  33. data/lib/confium/ffi.rb +4 -4
  34. data/lib/confium/lib.rb +18 -19
  35. data/lib/confium/pki/certificate_builder.rb +3 -3
  36. data/lib/confium/pki/cms/signed_data_builder.rb +10 -10
  37. data/lib/confium/pki/cms.rb +1 -1
  38. data/lib/confium/pki/cnml.rb +8 -8
  39. data/lib/confium/pki.rb +1 -1
  40. data/lib/confium/policy.rb +13 -13
  41. data/lib/confium/secure_bytes.rb +91 -89
  42. data/lib/confium/tc/coordinator.rb +7 -6
  43. data/lib/confium/tc/session.rb +5 -3
  44. data/lib/confium/tc/session_stub.rb +2 -2
  45. data/lib/confium/tc/share_file.rb +13 -13
  46. data/lib/confium/tc.rb +2 -2
  47. data/lib/confium/version.rb +1 -1
  48. data/lib/confium.rb +20 -20
  49. metadata +2 -2
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Raised when an out-of-range index is supplied.
4
- class Confium::IndexError < Confium::Error
5
- attr_reader :index, :valid_range
4
+ module Confium
5
+ class IndexError < Confium::Error
6
+ attr_reader :index, :valid_range
6
7
 
7
- def initialize(message = nil, details_hash = nil, **kwargs)
8
- message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
9
- @index = kwargs.delete(:index)
10
- @valid_range = kwargs.delete(:valid_range)
11
- super(message, details: { index: @index, valid_range: @valid_range, **kwargs })
8
+ def initialize(message = nil, details_hash = nil, **kwargs)
9
+ message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
10
+ @index = kwargs.delete(:index)
11
+ @valid_range = kwargs.delete(:valid_range)
12
+ super(message, details: { index: @index, valid_range: @valid_range, **kwargs })
13
+ end
12
14
  end
13
15
  end
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Raised when a referenced slot/cert/share is not present.
4
- class Confium::NotFoundError < Confium::Error
5
- attr_reader :kind, :identifier
4
+ module Confium
5
+ class NotFoundError < Confium::Error
6
+ attr_reader :kind, :identifier
6
7
 
7
- def initialize(message = nil, details_hash = nil, **kwargs)
8
- message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
9
- @kind = kwargs.delete(:kind)
10
- @identifier = kwargs.delete(:identifier)
11
- super(message, details: { kind: @kind, identifier: @identifier, **kwargs })
8
+ def initialize(message = nil, details_hash = nil, **kwargs)
9
+ message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
10
+ @kind = kwargs.delete(:kind)
11
+ @identifier = kwargs.delete(:identifier)
12
+ super(message, details: { kind: @kind, identifier: @identifier, **kwargs })
13
+ end
12
14
  end
13
15
  end
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Raised when input cannot be parsed (bad JSON, malformed PEM, etc.).
4
- class Confium::ParseError < Confium::Error
5
- attr_reader :format, :offset
4
+ module Confium
5
+ class ParseError < Confium::Error
6
+ attr_reader :format, :offset
6
7
 
7
- def initialize(message = nil, details_hash = nil, **kwargs)
8
- message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
9
- @format = kwargs.delete(:format)
10
- @offset = kwargs.delete(:offset)
11
- super(message, details: { format: @format, offset: @offset, **kwargs })
8
+ def initialize(message = nil, details_hash = nil, **kwargs)
9
+ message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
10
+ @format = kwargs.delete(:format)
11
+ @offset = kwargs.delete(:offset)
12
+ super(message, details: { format: @format, offset: @offset, **kwargs })
13
+ end
12
14
  end
13
15
  end
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Raised when a FIPS / jurisdictional policy is violated.
4
- class Confium::PolicyViolationError < Confium::Error
5
- attr_reader :policy, :violation
4
+ module Confium
5
+ class PolicyViolationError < Confium::Error
6
+ attr_reader :policy, :violation
6
7
 
7
- def initialize(message = nil, details_hash = nil, **kwargs)
8
- message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
9
- @policy = kwargs.delete(:policy)
10
- @violation = kwargs.delete(:violation)
11
- super(message, details: { policy: @policy, violation: @violation, **kwargs })
8
+ def initialize(message = nil, details_hash = nil, **kwargs)
9
+ message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
10
+ @policy = kwargs.delete(:policy)
11
+ @violation = kwargs.delete(:violation)
12
+ super(message, details: { policy: @policy, violation: @violation, **kwargs })
13
+ end
12
14
  end
13
15
  end
@@ -2,13 +2,15 @@
2
2
 
3
3
  # Raised when a Shamir/threshold operation fails (insufficient shares,
4
4
  # duplicate coordinates, etc.).
5
- class Confium::ThresholdError < Confium::Error
6
- attr_reader :have_count, :need_count
5
+ module Confium
6
+ class ThresholdError < Confium::Error
7
+ attr_reader :have_count, :need_count
7
8
 
8
- def initialize(message = nil, details_hash = nil, **kwargs)
9
- message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
10
- @have_count = kwargs.delete(:have_count)
11
- @need_count = kwargs.delete(:need_count)
12
- super(message, details: { have_count: @have_count, need_count: @need_count, **kwargs })
9
+ def initialize(message = nil, details_hash = nil, **kwargs)
10
+ message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
11
+ @have_count = kwargs.delete(:have_count)
12
+ @need_count = kwargs.delete(:need_count)
13
+ super(message, details: { have_count: @have_count, need_count: @need_count, **kwargs })
14
+ end
13
15
  end
14
16
  end
@@ -1,12 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Raised when a CMS signer_info cannot be resolved to a certificate.
4
- class Confium::UnresolvedSignerError < Confium::Error
5
- attr_reader :signer_index
4
+ module Confium
5
+ class UnresolvedSignerError < Confium::Error
6
+ attr_reader :signer_index
6
7
 
7
- def initialize(message = nil, details_hash = nil, **kwargs)
8
- message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
9
- @signer_index = kwargs.delete(:signer_index)
10
- super(message, details: { signer_index: @signer_index, **kwargs })
8
+ def initialize(message = nil, details_hash = nil, **kwargs)
9
+ message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
10
+ @signer_index = kwargs.delete(:signer_index)
11
+ super(message, details: { signer_index: @signer_index, **kwargs })
12
+ end
11
13
  end
12
14
  end
@@ -2,14 +2,16 @@
2
2
 
3
3
  # Raised when input is well-formed but semantically invalid (wrong size,
4
4
  # out-of-range value, etc.).
5
- class Confium::ValidationError < Confium::Error
6
- attr_reader :param, :expected, :actual
5
+ module Confium
6
+ class ValidationError < Confium::Error
7
+ attr_reader :param, :expected, :actual
7
8
 
8
- def initialize(message = nil, details_hash = nil, **kwargs)
9
- message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
10
- @param = kwargs.delete(:param)
11
- @expected = kwargs.delete(:expected)
12
- @actual = kwargs.delete(:actual)
13
- super(message, details: { param: @param, expected: @expected, actual: @actual, **kwargs })
9
+ def initialize(message = nil, details_hash = nil, **kwargs)
10
+ message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
11
+ @param = kwargs.delete(:param)
12
+ @expected = kwargs.delete(:expected)
13
+ @actual = kwargs.delete(:actual)
14
+ super(message, details: { param: @param, expected: @expected, actual: @actual, **kwargs })
15
+ end
14
16
  end
15
17
  end
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Raised when a signature / hash / proof fails to verify.
4
- class Confium::VerificationError < Confium::Error
5
- attr_reader :signer_index, :algorithm
4
+ module Confium
5
+ class VerificationError < Confium::Error
6
+ attr_reader :signer_index, :algorithm
6
7
 
7
- def initialize(message = nil, details_hash = nil, **kwargs)
8
- message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
9
- @signer_index = kwargs.delete(:signer_index)
10
- @algorithm = kwargs.delete(:algorithm)
11
- super(message, details: { signer_index: @signer_index, algorithm: @algorithm, **kwargs })
8
+ def initialize(message = nil, details_hash = nil, **kwargs)
9
+ message, kwargs = Confium::Errors::Coerce.args(message, details_hash, kwargs)
10
+ @signer_index = kwargs.delete(:signer_index)
11
+ @algorithm = kwargs.delete(:algorithm)
12
+ super(message, details: { signer_index: @signer_index, algorithm: @algorithm, **kwargs })
13
+ end
12
14
  end
13
15
  end
@@ -23,4 +23,4 @@ module Confium
23
23
  end
24
24
  end
25
25
 
26
- require_relative "errors/coerce"
26
+ require_relative 'errors/coerce'
data/lib/confium/ffi.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "ffi"
3
+ require 'ffi'
4
4
 
5
5
  # {Confium::FFI} is the namespace for everything that touches the native
6
6
  # Confium shared library through Ruby-FFI.
@@ -16,8 +16,8 @@ require "ffi"
16
16
  # migrated into `Confium::FFI::Library` in a follow-up.
17
17
  module Confium
18
18
  module FFI
19
- autoload :Library, "confium/ffi/library"
20
- autoload :Error, "confium/ffi/error"
21
- autoload :Options, "confium/ffi/options"
19
+ autoload :Library, 'confium/ffi/library'
20
+ autoload :Error, 'confium/ffi/error'
21
+ autoload :Options, 'confium/ffi/options'
22
22
  end
23
23
  end
data/lib/confium/lib.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'ffi'
2
4
 
3
5
  module Confium
@@ -5,30 +7,27 @@ module Confium
5
7
  extend ::FFI::Library
6
8
 
7
9
  FFI_LAYOUT = {
8
- cfm_create: [ %i[pointer], :uint32 ],
9
- cfm_destroy: [ %i[pointer], :uint32 ],
10
- cfm_plugin_load: [ %i[pointer string string pointer pointer], :uint32 ],
11
- cfm_hash_create: [ %i[pointer pointer pointer pointer pointer pointer], :uint32 ],
12
- cfm_hash_output_size: [ %i[pointer pointer], :uint32 ],
13
- cfm_hash_block_size: [ %i[pointer pointer], :uint32 ],
14
- cfm_hash_update: [ %i[pointer pointer uint32], :uint32 ],
15
- cfm_hash_reset: [ %i[pointer], :uint32 ],
16
- cfm_hash_clone: [ %i[pointer pointer], :uint32 ],
17
- cfm_hash_finalize: [ %i[pointer pointer uint32], :uint32 ],
18
- cfm_hash_destroy: [ %i[pointer], :void ],
10
+ cfm_create: [%i[pointer], :uint32],
11
+ cfm_destroy: [%i[pointer], :uint32],
12
+ cfm_plugin_load: [%i[pointer string string pointer pointer], :uint32],
13
+ cfm_hash_create: [%i[pointer pointer pointer pointer pointer pointer], :uint32],
14
+ cfm_hash_output_size: [%i[pointer pointer], :uint32],
15
+ cfm_hash_block_size: [%i[pointer pointer], :uint32],
16
+ cfm_hash_update: [%i[pointer pointer uint32], :uint32],
17
+ cfm_hash_reset: [%i[pointer], :uint32],
18
+ cfm_hash_clone: [%i[pointer pointer], :uint32],
19
+ cfm_hash_finalize: [%i[pointer pointer uint32], :uint32],
20
+ cfm_hash_destroy: [%i[pointer], :void]
19
21
  }.freeze
20
22
 
21
- ffi_lib([ENV["CONFIUM_LIB"], "confium", "libconfium"].compact)
23
+ ffi_lib([ENV.fetch('CONFIUM_LIB', nil), 'confium', 'libconfium'].compact)
22
24
 
23
25
  FFI_LAYOUT.each do |func, ary|
24
- begin
25
- class_eval do
26
- attach_function(func, ary.first, ary.last)
27
- end
28
- rescue ::FFI::NotFoundError
29
- # that's okay
26
+ class_eval do
27
+ attach_function(func, ary.first, ary.last)
30
28
  end
29
+ rescue ::FFI::NotFoundError
30
+ # that's okay
31
31
  end
32
-
33
32
  end
34
33
  end
@@ -22,8 +22,8 @@ module Confium
22
22
  attr_accessor :subject, :issuer, :serial, :not_before, :not_after
23
23
 
24
24
  def initialize
25
- @subject = ""
26
- @issuer = nil # nil = self-signed
25
+ @subject = ''
26
+ @issuer = nil # nil = self-signed
27
27
  @serial = rand(1..(1 << 128))
28
28
  @not_before = Time.now
29
29
  @not_after = Time.now + (365 * 24 * 3600)
@@ -52,7 +52,7 @@ module Confium
52
52
  not_before: @not_before.iso8601,
53
53
  not_after: @not_after.iso8601,
54
54
  algorithm: algorithm.to_s,
55
- public_key_hex: kp["public_key"].unpack1("H*"),
55
+ public_key_hex: kp['public_key'].unpack1('H*')
56
56
  }
57
57
  end
58
58
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "json"
4
- require "digest"
3
+ require 'json'
4
+ require 'digest'
5
5
 
6
6
  # Confium::PKI::CMS::SignedDataBuilder — construct CMS SignedData
7
7
  # envelopes with one or more signers.
@@ -27,8 +27,8 @@ module Confium
27
27
  attr_accessor :content
28
28
 
29
29
  SIGNATURE_ALGORITHM_OID = {
30
- ed25519: "1.3.101.112",
31
- ecdsa_p256: "1.2.840.10045.4.3.2",
30
+ ed25519: '1.3.101.112',
31
+ ecdsa_p256: '1.2.840.10045.4.3.2'
32
32
  }.freeze
33
33
 
34
34
  def initialize
@@ -46,7 +46,7 @@ module Confium
46
46
  @signers << {
47
47
  cert_der: cert_der,
48
48
  private_key: private_key,
49
- algorithm: algorithm,
49
+ algorithm: algorithm
50
50
  }
51
51
  end
52
52
 
@@ -57,8 +57,8 @@ module Confium
57
57
  #
58
58
  # @return [Confium::PKI::CMS::SignedData]
59
59
  def build
60
- raise ArgumentError, "at least one signer is required" if @signers.empty?
61
- raise ArgumentError, "#content is required (detached builder)" if @content.nil?
60
+ raise ArgumentError, 'at least one signer is required' if @signers.empty?
61
+ raise ArgumentError, '#content is required (detached builder)' if @content.nil?
62
62
 
63
63
  primary = @signers.first
64
64
  payload_bytes = @content.respond_to?(:bytes) ? @content.bytes : @content
@@ -68,7 +68,7 @@ module Confium
68
68
  SignedData.build_detached(
69
69
  signature,
70
70
  algorithm_oid,
71
- @signers.map { |s| s[:cert_der] },
71
+ @signers.map { |s| s[:cert_der] }
72
72
  )
73
73
  end
74
74
 
@@ -78,10 +78,10 @@ module Confium
78
78
  case algorithm
79
79
  when :ed25519
80
80
  result = Confium::Composite.sign_ed25519(private_key, payload)
81
- result.fetch("signature")
81
+ result.fetch('signature')
82
82
  when :ecdsa_p256
83
83
  result = Confium::TC::FrostP256.sign(private_key, payload)
84
- result.fetch("signature")
84
+ result.fetch('signature')
85
85
  else
86
86
  raise ArgumentError, "unsupported algorithm: #{algorithm.inspect}"
87
87
  end
@@ -9,7 +9,7 @@
9
9
  module Confium
10
10
  module PKI
11
11
  module CMS
12
- autoload :SignedDataBuilder, "confium/pki/cms/signed_data_builder"
12
+ autoload :SignedDataBuilder, 'confium/pki/cms/signed_data_builder'
13
13
  end
14
14
  end
15
15
  end
@@ -16,18 +16,18 @@ module Confium
16
16
  # Required X.509 v3 extensions for a CNML certificate.
17
17
  REQUIRED_EXTENSIONS = {
18
18
  # Standard X.509 extensions required by CNML:
19
- "2.5.29.19" => "basicConstraints (CA=true for IA certs, CA=false for leaf)",
20
- "2.5.29.15" => "keyUsage (digitalSignature for signing certs)",
21
- "2.5.29.37" => "extKeyUsage (id-kp-OCSPSigning or custom CNML OIDs)",
22
- "2.5.29.14" => "subjectKeyIdentifier (required for CMS signer resolution)",
23
- "2.5.29.35" => "authorityKeyIdentifier (required for chain building)",
19
+ '2.5.29.19' => 'basicConstraints (CA=true for IA certs, CA=false for leaf)',
20
+ '2.5.29.15' => 'keyUsage (digitalSignature for signing certs)',
21
+ '2.5.29.37' => 'extKeyUsage (id-kp-OCSPSigning or custom CNML OIDs)',
22
+ '2.5.29.14' => 'subjectKeyIdentifier (required for CMS signer resolution)',
23
+ '2.5.29.35' => 'authorityKeyIdentifier (required for chain building)'
24
24
  }.freeze
25
25
 
26
26
  # Optional but recommended extensions.
27
27
  OPTIONAL_EXTENSIONS = {
28
- "2.5.29.31" => "cRLDistributionPoints (for revocation checking)",
29
- "2.5.29.32" => "certificatePolicies (CNML policy OID)",
30
- "1.3.6.1.5.5.7.1.1" => "authorityInfoAccess (OCSP responder URL)",
28
+ '2.5.29.31' => 'cRLDistributionPoints (for revocation checking)',
29
+ '2.5.29.32' => 'certificatePolicies (CNML policy OID)',
30
+ '1.3.6.1.5.5.7.1.1' => 'authorityInfoAccess (OCSP responder URL)'
31
31
  }.freeze
32
32
 
33
33
  # CNML certificate roles (maps to ActorType in Confium::Identity).
data/lib/confium/pki.rb CHANGED
@@ -8,6 +8,6 @@
8
8
  # extend the native surface.
9
9
  module Confium
10
10
  module PKI
11
- autoload :CMS, "confium/pki/cms"
11
+ autoload :CMS, 'confium/pki/cms'
12
12
  end
13
13
  end
@@ -24,29 +24,29 @@ module Confium
24
24
  JURISDICTIONS = {
25
25
  # EU: eIDAS + GDPR alignment. RSA >= 2048, ECDSA P-256+.
26
26
  eu: {
27
- rsa: 2048,
27
+ rsa: 2048,
28
28
  ecdsa_p256: 256,
29
29
  ecdsa_p384: 384,
30
- ed25519: 256,
31
- name: "European Union (eIDAS)",
30
+ ed25519: 256,
31
+ name: 'European Union (eIDAS)'
32
32
  },
33
33
  # US: NIST SP 800-131A. RSA >= 2048, ECDSA P-256+, SHA-1 legacy.
34
34
  us: {
35
- rsa: 2048,
35
+ rsa: 2048,
36
36
  ecdsa_p256: 256,
37
37
  ecdsa_p384: 384,
38
- ed25519: 256,
38
+ ed25519: 256,
39
39
  sha1_legacy: true,
40
- name: "United States (NIST SP 800-131A)",
40
+ name: 'United States (NIST SP 800-131A)'
41
41
  },
42
42
  # OIML CNML: international, follows BIPM recommendations.
43
43
  cnml: {
44
- rsa: 2048,
44
+ rsa: 2048,
45
45
  ecdsa_p256: 256,
46
46
  ecdsa_p384: 384,
47
- ed25519: 256,
48
- name: "OIML CNML (BIPM)",
49
- },
47
+ ed25519: 256,
48
+ name: 'OIML CNML (BIPM)'
49
+ }
50
50
  }.freeze
51
51
 
52
52
  class << self
@@ -77,7 +77,7 @@ module Confium
77
77
  # FIPS 186-5 draft); ECDSA P-256/P-384 are.
78
78
  # @param value [Boolean]
79
79
  def fips_mode=(value)
80
- @fips_mode = !!value
80
+ @fips_mode = !value.nil?
81
81
  @jurisdiction = :us if @fips_mode && @jurisdiction.nil?
82
82
  end
83
83
 
@@ -98,7 +98,7 @@ module Confium
98
98
  raise Confium::PolicyViolationError.new(
99
99
  "algorithm #{alg} is not FIPS-approved",
100
100
  policy: :fips,
101
- violation: :unapproved_algorithm,
101
+ violation: :unapproved_algorithm
102
102
  )
103
103
  end
104
104
  end
@@ -115,7 +115,7 @@ module Confium
115
115
  raise Confium::PolicyViolationError.new(
116
116
  "#{alg} key size #{key_bits} below #{min_bits} for #{@jurisdiction}",
117
117
  policy: @jurisdiction,
118
- violation: :key_too_small,
118
+ violation: :key_too_small
119
119
  )
120
120
  end
121
121