cddl 0.10.2 → 0.10.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33adef2ddb191ca70e7ad3742684cea679e675fe0169a139c9fa5bcc59abfaa6
4
- data.tar.gz: 7b7b7d2cd0623645d6dca87c5c7a8a3d40540e7eec390411e9cbf3adcc6f7c9d
3
+ metadata.gz: b3b0177b945919083ba2e0595570d098809b87839cb86e823dd54c62f225ad6b
4
+ data.tar.gz: 45302758ba30682f746f9b515cd293a5ac0883b2b126d6f74cd13a4911286e9e
5
5
  SHA512:
6
- metadata.gz: b4a8ccd11e9dbf1b0ebf2541c03691a94a8430538fbe81db3bd178a2fab1732626114689d305048e88fb54c3336f0e95853c86f8336586d722df90639f82efa6
7
- data.tar.gz: 1c6494a0fa4ead8ea548f61f3af5595dde99707359ce8aa8695c074288248334849f2452cae52620541bb762c9cf3979b159f415a1b787009d1061df54d849b5
6
+ metadata.gz: d613c36a0b4e7e1a18c68c1a2c5df9b0c46389936fdc063465bc8c130ba470b5c6467872fd55befa47972ea8cce8362f45a2164e2ee32c02539f29bd45fb1279
7
+ data.tar.gz: 6dca2e75e676eb00aba31e03671b2baf37568a2e4eb8fb0b506c8b02829efb88d6efda323891962e6ca3644be4added36482ee555bbf4d13565517c59cbaf397
data/cddl.gemspec CHANGED
@@ -1,21 +1,23 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'cddl'
3
- s.version = '0.10.2'
3
+ s.version = '0.10.5'
4
4
  s.summary = "CDDL generator and validator."
5
5
  s.description = %{A parser, generator, and validator for CDDL}
6
6
  s.add_dependency('cbor-diag')
7
- s.add_dependency('abnc')
7
+ s.add_dependency('abnc', '~> 0.1.1')
8
8
  s.add_dependency('json_pure')
9
9
  s.add_dependency('abnftt')
10
10
  s.add_dependency('regexp-examples') # , '1.1.0')
11
11
  s.add_dependency('colorize')
12
12
  s.add_dependency('base32', '~> 0.3')
13
+ s.add_dependency('base45_lite', '~> 1.0')
14
+ s.add_dependency('scanf', '~> 1.0')
13
15
  s.files = `git ls-files`.split("\n").grep(/^[a-z]/)
14
16
  s.files = Dir['lib/**/*.rb'] + %w(cddl.gemspec) + Dir['data/**/*.abnf'] + Dir['data/**/*.cddl'] + Dir['test-data/**/*.cddl'] + Dir['test/**/*.rb']
15
17
  s.require_path = 'lib'
16
18
  s.executables = ['cddl']
17
19
  s.default_executable = 'cddl'
18
- s.required_ruby_version = '>= 2.0'
20
+ s.required_ruby_version = '>= 2.3'
19
21
  s.author = "Carsten Bormann"
20
22
  s.email = "cabo@tzi.org"
21
23
  s.homepage = "http://github.com/cabo/cddl"
data/data/cddl.abnf CHANGED
@@ -13,7 +13,7 @@ genericarg = "<" S type1 S *("," S type1 S ) ">"
13
13
  type = type1 S *("/" S type1 S)
14
14
 
15
15
  type1 = type2 [S (rangeop / annotator) S type2]
16
- / "#" "6" ["." uint] "(" S type S ")" ; note no space!
16
+ / "#" "6" ["." tagnumber] "(" S type S ")" ; note no space!
17
17
  / "#" DIGIT ["." uint] ; major/ai
18
18
  / "#" ; any
19
19
  / "~" S typename [genericarg]
@@ -22,6 +22,8 @@ type1 = type2 [S (rangeop / annotator) S type2]
22
22
  / "&" S "(" S group S ")"
23
23
  / "&" S groupname [genericarg]
24
24
 
25
+ tagnumber = uint / ("<" type ">")
26
+
25
27
  type2 = value
26
28
  / typename [genericarg]
27
29
  / "(" type ")"
data/lib/cddl.rb CHANGED
@@ -2,11 +2,14 @@ require 'abnc'
2
2
  require 'pp'
3
3
  require 'pathname'
4
4
  require 'cbor-pure' unless defined?(CBOR::Tagged)
5
+ require 'cbor-deterministic'
5
6
  require 'regexp-examples'
6
7
  require 'abnftt'
7
8
  require 'colorize'
8
9
  require 'base64'
9
10
  require 'base32'
11
+ require 'base45_lite'
12
+ require 'scanf'
10
13
 
11
14
  module CDDL
12
15
 
@@ -267,6 +270,21 @@ module CDDL
267
270
  l.map {|l| l.sub(/^ {0,#{indent}}/, "")}.join
268
271
  end
269
272
 
273
+ def unpack_array_to_sequence(content, where)
274
+ # remove the first head
275
+ n = case content.getbyte(0) - (4 << 5)
276
+ when 0..23; 1
277
+ when 24; 2
278
+ when 25; 3
279
+ when 26; 5
280
+ when 27; 9 # unlikely :-)
281
+ else fail ".cborseq sequence for #{where} not an array"
282
+ end
283
+ content[0...n] = ''
284
+ content
285
+ end
286
+
287
+
270
288
  # Memoize a bit here
271
289
 
272
290
  REGEXP_FOR_STRING = Hash.new {|h, k|
@@ -405,7 +423,11 @@ module CDDL
405
423
  when 3
406
424
  gen_word
407
425
  when 6
408
- CBOR::Tagged.new(where[2], generate1(where[3]))
426
+ tn = Integer === where[2] ? where[2] : generate1(where[2])
427
+ unless Integer === tn && tn >= 0
428
+ fail "Can't generate a tag number out of #{where[2]}"
429
+ end
430
+ CBOR::Tagged.new(tn, generate1(where[3]))
409
431
  when 7
410
432
  case where[2]
411
433
  when nil
@@ -534,8 +556,7 @@ module CDDL
534
556
  warn "HUH gen #{where.inspect} #{try.inspect}" unless try.nil?
535
557
  end
536
558
  end
537
- 32.times do
538
- content = generate1(target)
559
+ try_generate(target) do |content|
539
560
  if validate1(content, where)
540
561
  return content
541
562
  end
@@ -561,22 +582,18 @@ module CDDL
561
582
  end
562
583
  enc = bytes ? Encoding::BINARY : Encoding::UTF_8
563
584
  out.force_encoding(enc)
564
- when :cbor, :cborseq
585
+ when :cbor, :cborseq, :cbordet, :cborseqdet
565
586
  unless target == [:prim, 2]
566
587
  fail "Don't know yet how to generate #{where}"
567
588
  end
568
- content = CBOR::encode(generate1(control))
569
- if conop == :cborseq
589
+ input = generate1(control)
590
+ if conop == :cbordet || conop == :cborseqdet
591
+ input = input.cbor_prepare_deterministic
592
+ end
593
+ content = CBOR::encode(input)
594
+ if conop == :cborseq || conop == :cborseqdet
570
595
  # remove the first head
571
- n = case content.getbyte(0) - (4 << 5)
572
- when 0..23; 1
573
- when 24; 2
574
- when 25; 3
575
- when 26; 5
576
- when 27; 9 # unlikely :-)
577
- else fail "Generated .cborseq sequence for #{where} not an array"
578
- end
579
- content[0...n] = ''
596
+ content = unpack_array_to_sequence(content, where)
580
597
  end
581
598
  content
582
599
  when :json
@@ -592,25 +609,28 @@ module CDDL
592
609
  content = Integer(generate1(control)).to_s
593
610
  content
594
611
  when :join
595
- content = generate1(control)
596
- unless Array === content &&
597
- content.all? {|x| String === x &&
598
- ((target == [:prim, 2] && x.encoding == Encoding::BINARY) ||
599
- (target == [:prim, 3] && x.encoding != Encoding::BINARY))}
600
- fail "Don't know yet how to generate #{where}"
601
- end
602
- content = content.join
603
- content
604
- when :b64u, :b64c, :b32, :h32, :hex, :hexlc, :hexuc
605
- content = generate1(control)
606
- unless String === content
607
- fail "Don't know yet how to generate #{where}"
612
+ try_generate(control) do |content|
613
+ if Array === content &&
614
+ content.all? {|x| String === x} &&
615
+ Set[content.map {|x| x.encoding}].size == 1
616
+ content = content.join
617
+ if validate1(content, target)
618
+ return content
619
+ end
620
+ end
608
621
  end
609
- content = case conop
610
- when :b64u
622
+ fail "Don't know yet how to generate #{where}"
623
+ when :b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy",
624
+ :b45, :b32, :h32, :hex, :hexlc, :hexuc
625
+ try_generate(control) do |content|
626
+ if String === content
627
+ content = case conop
628
+ when :b64u, :"b64u-sloppy"
611
629
  Base64.urlsafe_encode64(content, padding: false)
612
- when :b64c
630
+ when :b64c, :"b64c-sloppy"
613
631
  Base64.strict_encode64(content)
632
+ when :b45
633
+ Base45Lite.encode(content)
614
634
  when :b32
615
635
  Base32.table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
616
636
  Base32.encode(content).gsub("=", "")
@@ -623,10 +643,32 @@ module CDDL
623
643
  content.unpack("H*")[0]
624
644
  else fail "Cannot happen"
625
645
  end
626
- content
646
+ if validate1(content, target)
647
+ return content
648
+ end
649
+ end
650
+ end
651
+ fail "Not smart enough to generate #{where}"
652
+ when :printf
653
+ try_generate(control) do |content|
654
+ if Array === content && content.size >= 1
655
+ fmt, *data = content
656
+ if String === fmt
657
+ begin
658
+ content = fmt % data
659
+ if validate1(content, target)
660
+ return content
661
+ end
662
+ rescue ArgumentError => e
663
+ # be verbose about mismatches here
664
+ @last_message << "\n** #{fmt.inspect} ArgumentError #{e}"
665
+ end
666
+ end
667
+ end
668
+ end
669
+ fail "Not smart enough to generate #{where}#{@last_message}"
627
670
  when :within, :and
628
- 32.times do
629
- content = generate1(target)
671
+ try_generate(target) do |content|
630
672
  if validate1(content, control)
631
673
  return content
632
674
  elsif conop == :within
@@ -654,6 +696,13 @@ module CDDL
654
696
  end
655
697
  end
656
698
 
699
+ def try_generate(target)
700
+ 32.times do
701
+ content = generate1(target)
702
+ yield content # should return if success
703
+ end
704
+ end
705
+
657
706
  VALUE_TYPE = {text: String, bytes: String, int: Integer, float: Float}
658
707
  SIMPLE_VALUE = {
659
708
  [:prim, 7, 20] => [true, false, :bool],
@@ -701,6 +750,19 @@ module CDDL
701
750
  }]
702
751
  end
703
752
 
753
+
754
+ def extract_arg0(t)
755
+ return [false] unless t[0] == :array
756
+ [true,
757
+ (el = t[1]
758
+ return [false] unless el[0..3] == [:member, 1, 1, nil]
759
+ ok, v, vt = extract_value(el[4])
760
+ return [false] unless ok
761
+ [v, vt]
762
+ ),
763
+ *t[2..-1]]
764
+ end
765
+
704
766
  def extract_feature(control, d)
705
767
  ok, v, vt = extract_value(control)
706
768
  if ok
@@ -1040,6 +1102,22 @@ module CDDL
1040
1102
  ann if validate1((CBOR::decode(d) rescue :BAD_CBOR), control)
1041
1103
  when :cborseq
1042
1104
  ann if validate1((CBOR::decode("\x9f".b << d << "\xff".b) rescue :BAD_CBOR), control)
1105
+ when :cbordet
1106
+ decoded = CBOR::decode(d) rescue :BAD_CBOR
1107
+ if d != decoded.to_deterministic_cbor
1108
+ @last_message = "CBOR #{d.inspect} not deterministically encoded"
1109
+ nil
1110
+ else
1111
+ ann if validate1(decoded, control)
1112
+ end
1113
+ when :cborseqdet
1114
+ decoded = CBOR::decode("\x9f".b << d << "\xff".b) rescue :BAD_CBOR
1115
+ if d != unpack_array_to_sequence(decoded.to_deterministic_cbor, d.inspect)
1116
+ @last_message = "CBOR Sequence #{d.inspect} not deterministically encoded"
1117
+ nil
1118
+ else
1119
+ ann if validate1(decoded, control)
1120
+ end
1043
1121
  when :json
1044
1122
  ann if validate1((JSON::load(d) rescue :BAD_JSON), control)
1045
1123
  when :decimal
@@ -1060,19 +1138,26 @@ module CDDL
1060
1138
  else
1061
1139
  fail "Don't know yet how to validate against #{where}"
1062
1140
  end
1063
- when :b64u, :b64c, :b32, :h32, :hex, :hexlc, :hexuc
1141
+ when :b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy", :b45, :b32, :h32, :hex, :hexlc, :hexuc
1064
1142
  ann if (
1065
1143
  String === d && (
1066
1144
  decoded = case conop
1067
1145
  when :b64u
1068
1146
  /=/ !~ d &&
1069
1147
  Base64.urlsafe_decode64(d)
1148
+ when :"b64u-sloppy"
1149
+ /[-_=]/ !~ d &&
1150
+ Base64.decode64(d.tr("+/", "-_"))
1070
1151
  when :b64c
1071
1152
  Base64.strict_decode64(d)
1153
+ when :"b64c-sloppy"
1154
+ Base64.decode64(d)
1072
1155
  when :b32
1073
1156
  /=/ !~ d &&
1074
1157
  (Base32.table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567") &&
1075
1158
  Base32.decode(d)
1159
+ when :b45
1160
+ Base45Lite.decode(d)
1076
1161
  when :h32
1077
1162
  /=/ !~ d &&
1078
1163
  (Base32.table = "0123456789ABCDEFGHIJKLMNOPQRSTUV") &&
@@ -1087,6 +1172,21 @@ module CDDL
1087
1172
  end
1088
1173
  ) && validate1(decoded.b, control)
1089
1174
  )
1175
+ when :printf
1176
+ ann if String === d && (
1177
+ ok, fmt, *v = extract_arg0(control)
1178
+ if ok && String == fmt[1]
1179
+ fmt = fmt[0]
1180
+ # warn "** ok #{ok.inspect} fmt #{fmt.inspect} v #{v.inspect}"
1181
+ decoded = d.scanf(fmt) # this is a bit too lenient, so let's do:
1182
+ encode_again = fmt % decoded
1183
+ if encode_again != d
1184
+ warn "** fmt #{fmt.inspect} d #{d.inspect} decoded #{decoded.inspect} encode_again #{encode_again.inspect}"
1185
+ else
1186
+ validate1(decoded, [:array, *v])
1187
+ end
1188
+ end
1189
+ )
1090
1190
  when :within
1091
1191
  if validate1(d, control)
1092
1192
  ann
@@ -1122,7 +1222,9 @@ module CDDL
1122
1222
  end
1123
1223
  d = CBOR::Tagged.new(t, d == 0 ? "".b : d.digits(256).reverse!.pack("C*"))
1124
1224
  end
1125
- CBOR::Tagged === d && d.tag == where[2] && validate1a(d.data, where[3])
1225
+ CBOR::Tagged === d && (
1226
+ Integer === where[2] ? d.tag == where[2] : validate1a(d.tag, where[2])
1227
+ ) && validate1a(d.data, where[3])
1126
1228
  when 7
1127
1229
  t, v = extract_value(where)
1128
1230
  if t
@@ -1441,11 +1543,15 @@ module CDDL
1441
1543
 
1442
1544
  BRACE = {"{" => :map, "[" => :array}
1443
1545
  RANGE_EXCLUDE_END = {".." => false, "..." => true}
1444
- SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp, :cbor, :cborseq, :within, :and,
1546
+ SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp,
1547
+ :cbor, :cborseq, :cbordet, :cborseqdet,
1548
+ :within, :and,
1445
1549
  :default, :lt, :le, :gt, :ge, :eq, :ne,
1446
1550
  :feature, :abnf, :abnfb, :det, :cat, :plus,
1447
1551
  :json, :decimal, :join,
1448
- :b64u, :b64c, :b32, :h32, :hex, :hexlc, :hexuc,
1552
+ :b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy",
1553
+ :b45, :b32, :h32, :hex, :hexlc, :hexuc,
1554
+ :printf,
1449
1555
  ]
1450
1556
 
1451
1557
  def type1(n, canbegroup = false)
@@ -1477,7 +1583,14 @@ module CDDL
1477
1583
  [:prim]
1478
1584
  when /\A#(\d+)/
1479
1585
  maj = $1.to_i
1480
- s = [:prim, maj, *n.children(:uint).map(&:to_s).map(&:to_i)]
1586
+ s = [:prim, maj]
1587
+ if tn = n.tagnumber
1588
+ if ui = tn.uint
1589
+ s << ui.to_s.to_i
1590
+ elsif tt = tn.type
1591
+ s << type(tt)
1592
+ end
1593
+ end
1481
1594
  if tagged_type = n.type
1482
1595
  s << type(tagged_type)
1483
1596
  end
@@ -0,0 +1 @@
1
+ a = text .b64c-sloppy 'mnoabcdue=='
@@ -0,0 +1,2 @@
1
+ a = text .printf (["%8d %06d", ~arr])
2
+ arr = [uint, uint]
@@ -0,0 +1 @@
1
+ my_label = text .printf (["0x%x: %a", 4711, 81.5])
@@ -0,0 +1,2 @@
1
+ my_alg_sha = hexlabel<4>
2
+ hexlabel<K> = text .printf (["0x%04x", K])
@@ -0,0 +1,2 @@
1
+ my_alg_sha = hexlabel<int>
2
+ hexlabel<K> = text .printf (["0x%04x", K])
@@ -0,0 +1,2 @@
1
+ any_alg = hexlabel<1..20>
2
+ hexlabel<K> = text .printf (["0x%04x", K])
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cddl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.2
4
+ version: 0.10.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carsten Bormann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-25 00:00:00.000000000 Z
11
+ date: 2024-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cbor-diag
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: abnc
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: 0.1.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: 0.1.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: json_pure
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +108,34 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0.3'
111
+ - !ruby/object:Gem::Dependency
112
+ name: base45_lite
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: scanf
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1.0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '1.0'
111
139
  description: A parser, generator, and validator for CDDL
112
140
  email: cabo@tzi.org
113
141
  executables:
@@ -133,6 +161,7 @@ files:
133
161
  - test-data/abnf3.cddl
134
162
  - test-data/ambig.cddl
135
163
  - test-data/b.cddl
164
+ - test-data/b64c-sloppy.cddl
136
165
  - test-data/b64c.cddl
137
166
  - test-data/b64u.cddl
138
167
  - test-data/badaddr.cddl
@@ -206,6 +235,11 @@ files:
206
235
  - test-data/oidbat.cddl
207
236
  - test-data/patch1.cddl
208
237
  - test-data/plus.cddl
238
+ - test-data/printf.cddl
239
+ - test-data/printf0.cddl
240
+ - test-data/printf1.cddl
241
+ - test-data/printf2.cddl
242
+ - test-data/printf3.cddl
209
243
  - test-data/reused_named_group.cddl
210
244
  - test-data/sasl.cddl
211
245
  - test-data/sequence.cddl
@@ -238,14 +272,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
238
272
  requirements:
239
273
  - - ">="
240
274
  - !ruby/object:Gem::Version
241
- version: '2.0'
275
+ version: '2.3'
242
276
  required_rubygems_version: !ruby/object:Gem::Requirement
243
277
  requirements:
244
278
  - - ">="
245
279
  - !ruby/object:Gem::Version
246
280
  version: '0'
247
281
  requirements: []
248
- rubygems_version: 3.4.2
282
+ rubygems_version: 3.4.10
249
283
  signing_key:
250
284
  specification_version: 4
251
285
  summary: CDDL generator and validator.