123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- package x509
- import (
- "encoding/json"
- "errors"
- "github.com/zmap/zcrypto/encoding/asn1"
- )
- type QCStatementASN struct {
- StatementID asn1.ObjectIdentifier
- StatementInfo asn1.RawValue `asn1:"optional"`
- }
- func (s *QCStatementASN) MarshalJSON() ([]byte, error) {
- aux := struct {
- ID string `json:"id,omitempty"`
- Value []byte `json:"value,omitempty"`
- }{
- ID: s.StatementID.String(),
- Value: s.StatementInfo.Bytes,
- }
- return json.Marshal(&aux)
- }
- type QCStatementsASN struct {
- QCStatements []QCStatementASN
- }
- // ETSI OIDS from https://www.etsi.org/deliver/etsi_en/319400_319499/31941205/02.02.03_20/en_31941205v020203a.pdf
- var (
- oidEtsiQcsQcCompliance = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 1}
- oidEtsiQcsQcLimitValue = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 2}
- oidEtsiQcsQcRetentionPeriod = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 3}
- oidEtsiQcsQcSSCD = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 4}
- oidEtsiQcsQcEuPDS = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 5}
- oidEtsiQcsQcType = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6}
- oidEtsiQcsQcCCLegislation = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 7}
- oidEtsiQcsQctEsign = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6, 1}
- oidEtsiQcsQctEseal = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6, 2}
- oidEtsiQcsQctWeb = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6, 3}
- )
- type QCStatements struct {
- StatementIDs []string `json:"ids,omitempty"`
- ParsedStatements *ParsedQCStatements `json:"parsed,omitempty"`
- }
- type ParsedQCStatements struct {
- ETSICompliance []bool `json:"etsi_compliance,omitempty"`
- SSCD []bool `json:"sscd,omitempty"`
- Types []QCType `json:"types,omitempty"`
- Limit []MonetaryValue `json:"limit,omitempty"`
- PDSLocations []PDSLocations `json:"pds_locations,omitempty"`
- RetentionPeriod []int `json:"retention_period,omitempty"`
- Legislation []QCLegistation `json:"legislation,omitempty"`
- }
- type MonetaryValue struct {
- Currency string `json:"currency,omitempty"`
- CurrencyNumber int `json:"currency_number,omitempty"`
- Amount int `json:"amount,omitempty"`
- Exponent int `json:"exponent,omitempty"`
- }
- type monetaryValueASNString struct {
- Currency string `asn1:"printable"`
- Amount int
- Exponent int
- }
- type monetaryValueASNNumber struct {
- Currency int
- Amount int
- Exponent int
- }
- type PDSLocations struct {
- Locations []PDSLocation `json:"locations,omitempty"`
- }
- type PDSLocation struct {
- URL string `json:"url,omitempty" asn1:"ia5"`
- Language string `json:"language,omitempty" asn1:"printable"`
- }
- type QCType struct {
- TypeIdentifiers []asn1.ObjectIdentifier
- }
- type QCLegistation struct {
- CountryCodes []string `json:"country_codes,omitempty"`
- }
- func (qt *QCType) MarshalJSON() ([]byte, error) {
- aux := struct {
- Types []string `json:"ids,omitempty"`
- }{
- Types: make([]string, len(qt.TypeIdentifiers)),
- }
- for idx := range qt.TypeIdentifiers {
- aux.Types[idx] = qt.TypeIdentifiers[idx].String()
- }
- return json.Marshal(&aux)
- }
- func (q *QCStatements) Parse(in *QCStatementsASN) error {
- q.StatementIDs = make([]string, len(in.QCStatements))
- known := ParsedQCStatements{}
- for i, s := range in.QCStatements {
- val := in.QCStatements[i].StatementInfo.FullBytes
- q.StatementIDs[i] = s.StatementID.String()
- if s.StatementID.Equal(oidEtsiQcsQcCompliance) {
- known.ETSICompliance = append(known.ETSICompliance, true)
- if val != nil {
- return errors.New("EtsiQcsQcCompliance QCStatement must not contain a statementInfo")
- }
- } else if s.StatementID.Equal(oidEtsiQcsQcLimitValue) {
- // TODO
- mvs := monetaryValueASNString{}
- mvn := monetaryValueASNNumber{}
- out := MonetaryValue{}
- if _, err := asn1.Unmarshal(val, &mvs); err == nil {
- out.Currency = mvs.Currency
- out.Amount = mvs.Amount
- out.Exponent = mvs.Exponent
- } else if _, err := asn1.Unmarshal(val, &mvn); err == nil {
- out.CurrencyNumber = mvn.Currency
- out.Amount = mvn.Amount
- out.Exponent = mvn.Exponent
- } else {
- return err
- }
- known.Limit = append(known.Limit, out)
- } else if s.StatementID.Equal(oidEtsiQcsQcRetentionPeriod) {
- var retentionPeriod int
- if _, err := asn1.Unmarshal(val, &retentionPeriod); err != nil {
- return err
- }
- known.RetentionPeriod = append(known.RetentionPeriod, retentionPeriod)
- } else if s.StatementID.Equal(oidEtsiQcsQcSSCD) {
- known.SSCD = append(known.SSCD, true)
- if val != nil {
- return errors.New("EtsiQcsQcSSCD QCStatement must not contain a statementInfo")
- }
- } else if s.StatementID.Equal(oidEtsiQcsQcEuPDS) {
- locations := make([]PDSLocation, 0)
- if _, err := asn1.Unmarshal(val, &locations); err != nil {
- return err
- }
- known.PDSLocations = append(known.PDSLocations, PDSLocations{
- Locations: locations,
- })
- } else if s.StatementID.Equal(oidEtsiQcsQcType) {
- typeIds := make([]asn1.ObjectIdentifier, 0)
- if _, err := asn1.Unmarshal(val, &typeIds); err != nil {
- return err
- }
- known.Types = append(known.Types, QCType{
- TypeIdentifiers: typeIds,
- })
- } else if s.StatementID.Equal(oidEtsiQcsQcCCLegislation) {
- countryCodes := make([]string, 0)
- if _, err := asn1.Unmarshal(val, &countryCodes); err != nil {
- return err
- }
- known.Legislation = append(known.Legislation, QCLegistation{
- CountryCodes: countryCodes,
- })
- }
- }
- q.ParsedStatements = &known
- return nil
- }
|