aboutsummaryrefslogtreecommitdiff
path: root/tcl_tests/pkcs7.tcl
blob: 4e9d1347de74a9a66f62bf7f798dc725df16ee88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package require base64
if {[info exists env(TOOLDIR)]} {
	lappend auto_path $env(TOOLDIR)
} {
	lappend auto_path "[file dirname [info script]]/../../maketool"
}
package require asn 0.7.1

namespace eval pkcs7 {
	namespace import ::asn::*
	namespace export *

	proc asnTag {data_var} {
		upvar $data_var data
		asnPeekByte data b
		return $b
	}

	proc envelopedData {der} {
		asnGetSequence der seq0
		asnGetObjectIdentifier seq0 id_envelopedData
		if {$id_envelopedData != {1 2 840 113549 1 7 3}} {
			error "Waited id-envelopedData, got $id_envelopedData"
		}
		asnGetContext seq0 n envelopedData
		if {$n != 0} {
			error "Waited context 0, got $n"
		}
		asnGetSequence envelopedData envelopedData
		asnGetInteger envelopedData version
		set originatorInfo {}
		if {[asnTag envelopedData] != 0x31} {
			asnGetContext envelopedData tag originatorInfo
		}
		asnGetSet envelopedData recipientInfos
		asnGetSequence envelopedData encryptedContentInfo
		set unprotectedAttrs {}
		if {[string length $envelopedData]} {
			asnGetContext envelopedData tag unprotectedAttrs
		}
		return [list $version $originatorInfo $recipientInfos $encryptedContentInfo $unprotectedAttrs $envelopedData]
	}

	proc recipientInfos {rIs} {
		set result {}
		while {[string length $rIs]} {
			asnGetSequence rIs inf
			asnGetInteger inf version
			set tag {}
			if {[asnTag inf] == 0x30} {
				asnGetSequence inf rid
			} {
				asnGetContext inf tag rid
			}
			asnGetSequence inf keyEncAlg
			asnGetOctetString inf encryptedKey
			lappend result [list $version [list $tag $rid] $keyEncAlg $encryptedKey]
		}
		return $result
	}

	proc subjectPublicKeyInfo {spki} {
		asnGetSequence spki algorithmIdentifier
		asnGetBitString spki subjectPublicKey
		list $algorithmIdentifier $subjectPublicKey $spki
	}

	proc algorithmIdentifier {ai} {
		asnGetObjectIdentifier ai oid
		set param {}
		if {[string length $ai]} {
			asnGetSequence ai param
		}
		return [list $oid $param $ai]
	}

	proc algorithmParamPKGOST {param} {
		asnGetObjectIdentifier param pubkey_param
		asnGetObjectIdentifier param digest_param
		set cipher_param {}
		if {[string length $param]} {
			asnGetObjectIdentifier param cipher_param
		}
		return [list $pubkey_param $digest_param $cipher_param $param]
	}

	proc keyTransportGOST {octet_string} {
		asnGetSequence octet_string inf
		asnGetSequence inf encryptedKey
		set transportParams {}
		if {[string length $inf]} {
			asnGetContext inf tag transportParams
		}
		return [list $encryptedKey $transportParams $inf]
	}

	proc encryptedKeyGOST {encryptedKeyAndMAC} {
		asnGetOctetString encryptedKeyAndMAC encryptedKey
		asnGetOctetString encryptedKeyAndMAC MAC
		list $encryptedKey $MAC $encryptedKeyAndMAC
	}

	proc transportParameters {transportParams} {
		asnGetObjectIdentifier transportParams encryptionParamSet
		set ephemeralPublicKey {}
		if {[asnTag transportParams] == 0xa0} {
			asnGetContext transportParams tag ephemeralPublicKey
		}
		asnGetOctetString transportParams ukm
		list $encryptionParamSet $ephemeralPublicKey $ukm $transportParams
	}

	proc encryptedContentInfo {eci} {
		asnGetObjectIdentifier eci oid
		asnGetSequence eci algorithmIdentifier
		set encryptedContent {}
		if {[string length $eci]} {
			asnGetContext eci tag encryptedContent
		}
		list $oid $algorithmIdentifier $encryptedContent $eci
	}

	proc algorithmParamEncGOST {param} {
		asnGetOctetString param ukm
		asnGetObjectIdentifier param encParam
		list $ukm $encParam $param
	}

	proc algorithm_oids_from_envelopedData {der} {
		set result {}
		foreach {v oI rIs eCI uAs t} [envelopedData $der] {
			# recipient infos
			set rin 0
			foreach rI [recipientInfos $rIs] {
				foreach {v rid kEA eK} $rI {
					# export (pubkey) algorithm identifier
					foreach {pk_oid param t} [algorithmIdentifier $kEA] {
						lappend result ri${rin}:kea=[join $pk_oid .]
						foreach {pkp dp cp t} [algorithmParamPKGOST $param] {
							lappend result \
								ri${rin}:kea:pkp=[join $pkp .] \
								ri${rin}:kea:dp=[join $dp .] \
								ri${rin}:kea:cp=[join $cp .]
						}
					}
					# encryptedKey encapsulated structure
					foreach {eK tPs t} [keyTransportGOST $eK] {
						# transport parameters
						foreach {ePS ePK ukm t} [transportParameters $tPs] {
							# encryption paramset
							lappend result ri${rin}:ktcp=[join $ePS .]
							# ephemeral public key
							if {[string length $ePK]} {
								foreach {aI sPK t} [subjectPublicKeyInfo $ePK] {
									# algorithm identifier
									foreach {pKI param t} [algorithmIdentifier $aI] {
										lappend result ri${rin}:ktepk=[join $pKI .]
										foreach {pkp dp cp t} [algorithmParamPKGOST $param] {
											lappend result \
												ri${rin}:ktepk:pkp=[join $pkp .] \
												ri${rin}:ktepk:dp=[join $dp .] \
												ri${rin}:ktepk:cp=[join $cp .]
										}
									}
								}
							}
						}
					}
				}
				incr rin
			}
			foreach {oid aI eC t} [encryptedContentInfo $eCI] {
				# algorithm identifier
				foreach {oid param t} [algorithmIdentifier $aI] {
					lappend result ea=[join $oid .]
					foreach {ukm oid t} [algorithmParamEncGOST $param] {
						lappend result ea:cp=[join $oid .]
					}
				}
			}
		}
		return $result
	}

}

package provide pkcs7 0.1