#!/usr/bin/env python
# Copyright 2019 The Chromium Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This script is called without any arguments to re-generate all of the *.pem
files in the script's directory.

The https://github.com/google/der-ascii tools must be in the PATH.
"""

import base64
import subprocess
import os


HEADER = "Generated by %s. Do not edit." % os.path.split(__file__)[1]


def Ascii2Der(txt):
  p = subprocess.Popen(['ascii2der'],
                        stdin=subprocess.PIPE,
                        stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE)
  stdout_data, stderr_data = p.communicate(txt)
  if p.returncode:
    raise RuntimeError('ascii2der returned %i: %s' % (p.returncode,
                                                      stderr_data))
  return stdout_data


def MakePemBlock(text, der, name):
  b64 = base64.b64encode(der)
  wrapped = '\n'.join(b64[pos:pos + 64] for pos in xrange(0, len(b64), 64))
  return '%s\n\n%s\n-----BEGIN %s-----\n%s\n-----END %s-----' % (
      HEADER, text, name, wrapped, name)


def Generate(path, dertext):
  der = Ascii2Der(dertext)
  data = MakePemBlock(dertext, der, 'AUTHORITY_KEY_IDENTIFIER')
  with open(path, "w") as f:
    f.write(data)


Generate('empty_sequence.pem', 'SEQUENCE {}')

Generate('key_identifier.pem', """
  SEQUENCE {
    [0 PRIMITIVE] { `DEADB00F`}
  }
""")

Generate('issuer_and_serial.pem', """
  SEQUENCE {
    [1] {
      [4] {
        SEQUENCE {
          SET {
            SEQUENCE {
              # commonName
              OBJECT_IDENTIFIER { 2.5.4.3 }
              UTF8String { "Root" }
            }
          }
        }
      }
    }
    [2 PRIMITIVE] { `274f` }
  }
""")

Generate('url_issuer_and_serial.pem', """
  SEQUENCE {
    [1] {
      [6 PRIMITIVE] { "http://example.com" }
    }
    [2 PRIMITIVE] { `274f` }
  }
""")

Generate('key_identifier_and_issuer_and_serial.pem', """
  SEQUENCE {
    [0 PRIMITIVE] { `DEADB00F`}
    [1] {
      [4] {
        SEQUENCE {
          SET {
            SEQUENCE {
              # commonName
              OBJECT_IDENTIFIER { 2.5.4.3 }
              UTF8String { "Root" }
            }
          }
        }
      }
    }
    [2 PRIMITIVE] { `274f` }
  }
""")

Generate('issuer_only.pem', """
  SEQUENCE {
    [1] {
      [4] {
        SEQUENCE {
          SET {
            SEQUENCE {
              # commonName
              OBJECT_IDENTIFIER { 2.5.4.3 }
              UTF8String { "Root" }
            }
          }
        }
      }
    }
  }
""")

Generate('serial_only.pem', """
  SEQUENCE {
    [2 PRIMITIVE] { `274f` }
  }
""")

Generate('invalid_contents.pem', """
  SEQUENCE {
    INTEGER {`1234`}
  }
""")

Generate('invalid_key_identifier.pem', """
  SEQUENCE {
    # Tag and Length for [0 PRIMITIVE], but no data.
    `8004`
  }
""")

Generate('invalid_issuer.pem', """
  SEQUENCE {
    [0 PRIMITIVE] { `DEADB00F`}
    # Tag and Length for [1] {...}, but no data.
    `a104`
  }
""")

Generate('invalid_serial.pem', """
  SEQUENCE {
    [0 PRIMITIVE] { `DEADB00F`}
    [1] {}
    # Tag and Length for [2 PRIMITIVE], but no data.
    `8204`
  }
""")

Generate('extra_contents_after_issuer_and_serial.pem', """
  SEQUENCE {
    [1] {
      [4] {
        SEQUENCE {
          SET {
            SEQUENCE {
              # commonName
              OBJECT_IDENTIFIER { 2.5.4.3 }
              UTF8String { "Root" }
            }
          }
        }
      }
    }
    [2 PRIMITIVE] { `274f` }
    INTEGER {`1234`}
  }
""")

Generate('extra_contents_after_extension_sequence.pem', """
  SEQUENCE {
    [0 PRIMITIVE] { `DEADB00F`}
  }
  INTEGER {`1234`}
""")
