733 lines
21 KiB
Go
733 lines
21 KiB
Go
|
// Copyright (c) 2016, Google Inc.
|
||
|
//
|
||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||
|
// purpose with or without fee is hereby granted, provided that the above
|
||
|
// copyright notice and this permission notice appear in all copies.
|
||
|
//
|
||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||
|
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||
|
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||
|
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||
|
|
||
|
package main
|
||
|
|
||
|
import (
|
||
|
"bufio"
|
||
|
"bytes"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"io/ioutil"
|
||
|
"os"
|
||
|
"os/exec"
|
||
|
"sort"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
func sanitizeName(in string) string {
|
||
|
in = strings.Replace(in, "-", "_", -1)
|
||
|
in = strings.Replace(in, ".", "_", -1)
|
||
|
in = strings.Replace(in, " ", "_", -1)
|
||
|
return in
|
||
|
}
|
||
|
|
||
|
type object struct {
|
||
|
name string
|
||
|
// shortName and longName are the short and long names, respectively. If
|
||
|
// one is missing, it takes the value of the other, but the
|
||
|
// corresponding SN_foo or LN_foo macro is not defined.
|
||
|
shortName, longName string
|
||
|
hasShortName, hasLongName bool
|
||
|
oid []int
|
||
|
encoded []byte
|
||
|
}
|
||
|
|
||
|
type objects struct {
|
||
|
// byNID is the list of all objects, indexed by nid.
|
||
|
byNID []object
|
||
|
// nameToNID is a map from object name to nid.
|
||
|
nameToNID map[string]int
|
||
|
}
|
||
|
|
||
|
func readNumbers(path string) (nameToNID map[string]int, numNIDs int, err error) {
|
||
|
in, err := os.Open(path)
|
||
|
if err != nil {
|
||
|
return nil, 0, err
|
||
|
}
|
||
|
defer in.Close()
|
||
|
|
||
|
nameToNID = make(map[string]int)
|
||
|
nidsSeen := make(map[int]struct{})
|
||
|
|
||
|
// Reserve NID 0 for NID_undef.
|
||
|
numNIDs = 1
|
||
|
nameToNID["undef"] = 0
|
||
|
nidsSeen[0] = struct{}{}
|
||
|
|
||
|
var lineNo int
|
||
|
scanner := bufio.NewScanner(in)
|
||
|
for scanner.Scan() {
|
||
|
line := scanner.Text()
|
||
|
lineNo++
|
||
|
withLine := func(err error) error {
|
||
|
return fmt.Errorf("%s:%d: %s", path, lineNo, err)
|
||
|
}
|
||
|
|
||
|
fields := strings.Fields(line)
|
||
|
if len(fields) == 0 {
|
||
|
// Skip blank lines.
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
// Each line is a name and a nid, separated by space.
|
||
|
if len(fields) != 2 {
|
||
|
return nil, 0, withLine(errors.New("syntax error"))
|
||
|
}
|
||
|
name := fields[0]
|
||
|
nid, err := strconv.Atoi(fields[1])
|
||
|
if err != nil {
|
||
|
return nil, 0, withLine(err)
|
||
|
}
|
||
|
if nid < 0 {
|
||
|
return nil, 0, withLine(errors.New("invalid NID"))
|
||
|
}
|
||
|
|
||
|
// NID_undef is implicitly defined.
|
||
|
if name == "undef" && nid == 0 {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
// Forbid duplicates.
|
||
|
if _, ok := nameToNID[name]; ok {
|
||
|
return nil, 0, withLine(fmt.Errorf("duplicate name %q", name))
|
||
|
}
|
||
|
if _, ok := nidsSeen[nid]; ok {
|
||
|
return nil, 0, withLine(fmt.Errorf("duplicate NID %d", nid))
|
||
|
}
|
||
|
|
||
|
nameToNID[name] = nid
|
||
|
nidsSeen[nid] = struct{}{}
|
||
|
|
||
|
if nid >= numNIDs {
|
||
|
numNIDs = nid + 1
|
||
|
}
|
||
|
}
|
||
|
if err := scanner.Err(); err != nil {
|
||
|
return nil, 0, fmt.Errorf("error reading %s: %s", path, err)
|
||
|
}
|
||
|
|
||
|
return nameToNID, numNIDs, nil
|
||
|
}
|
||
|
|
||
|
func parseOID(aliases map[string][]int, in []string) (oid []int, err error) {
|
||
|
if len(in) == 0 {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// The first entry may be a reference to a previous alias.
|
||
|
if alias, ok := aliases[sanitizeName(in[0])]; ok {
|
||
|
in = in[1:]
|
||
|
oid = append(oid, alias...)
|
||
|
}
|
||
|
|
||
|
for _, c := range in {
|
||
|
val, err := strconv.Atoi(c)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if val < 0 {
|
||
|
return nil, fmt.Errorf("negative component")
|
||
|
}
|
||
|
oid = append(oid, val)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func appendBase128(dst []byte, value int) []byte {
|
||
|
// Zero is encoded with one, not zero bytes.
|
||
|
if value == 0 {
|
||
|
return append(dst, 0)
|
||
|
}
|
||
|
|
||
|
// Count how many bytes are needed.
|
||
|
var l int
|
||
|
for n := value; n != 0; n >>= 7 {
|
||
|
l++
|
||
|
}
|
||
|
for ; l > 0; l-- {
|
||
|
b := byte(value>>uint(7*(l-1))) & 0x7f
|
||
|
if l > 1 {
|
||
|
b |= 0x80
|
||
|
}
|
||
|
dst = append(dst, b)
|
||
|
}
|
||
|
return dst
|
||
|
}
|
||
|
|
||
|
func encodeOID(oid []int) []byte {
|
||
|
if len(oid) < 2 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
var der []byte
|
||
|
der = appendBase128(der, 40*oid[0]+oid[1])
|
||
|
for _, value := range oid[2:] {
|
||
|
der = appendBase128(der, value)
|
||
|
}
|
||
|
return der
|
||
|
}
|
||
|
|
||
|
func readObjects(numPath, objectsPath string) (*objects, error) {
|
||
|
nameToNID, numNIDs, err := readNumbers(numPath)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
in, err := os.Open(objectsPath)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
defer in.Close()
|
||
|
|
||
|
// Implicitly define NID_undef.
|
||
|
objs := &objects{
|
||
|
byNID: make([]object, numNIDs),
|
||
|
nameToNID: make(map[string]int),
|
||
|
}
|
||
|
|
||
|
objs.byNID[0] = object{
|
||
|
name: "undef",
|
||
|
shortName: "UNDEF",
|
||
|
longName: "undefined",
|
||
|
hasShortName: true,
|
||
|
hasLongName: true,
|
||
|
}
|
||
|
objs.nameToNID["undef"] = 0
|
||
|
|
||
|
var module, nextName string
|
||
|
var lineNo int
|
||
|
longNamesSeen := make(map[string]struct{})
|
||
|
shortNamesSeen := make(map[string]struct{})
|
||
|
aliases := make(map[string][]int)
|
||
|
scanner := bufio.NewScanner(in)
|
||
|
for scanner.Scan() {
|
||
|
line := scanner.Text()
|
||
|
lineNo++
|
||
|
withLine := func(err error) error {
|
||
|
return fmt.Errorf("%s:%d: %s", objectsPath, lineNo, err)
|
||
|
}
|
||
|
|
||
|
// Remove comments.
|
||
|
idx := strings.IndexRune(line, '#')
|
||
|
if idx >= 0 {
|
||
|
line = line[:idx]
|
||
|
}
|
||
|
|
||
|
// Skip empty lines.
|
||
|
line = strings.TrimSpace(line)
|
||
|
if len(line) == 0 {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
if line[0] == '!' {
|
||
|
args := strings.Fields(line)
|
||
|
switch args[0] {
|
||
|
case "!module":
|
||
|
if len(args) != 2 {
|
||
|
return nil, withLine(errors.New("too many arguments"))
|
||
|
}
|
||
|
module = sanitizeName(args[1]) + "_"
|
||
|
case "!global":
|
||
|
module = ""
|
||
|
case "!Cname":
|
||
|
// !Cname directives override the name for the
|
||
|
// next object.
|
||
|
if len(args) != 2 {
|
||
|
return nil, withLine(errors.New("too many arguments"))
|
||
|
}
|
||
|
nextName = sanitizeName(args[1])
|
||
|
case "!Alias":
|
||
|
// !Alias directives define an alias for an OID
|
||
|
// without emitting an object.
|
||
|
if len(nextName) != 0 {
|
||
|
return nil, withLine(errors.New("!Cname directives may not modify !Alias directives."))
|
||
|
}
|
||
|
if len(args) < 3 {
|
||
|
return nil, withLine(errors.New("not enough arguments"))
|
||
|
}
|
||
|
aliasName := module + sanitizeName(args[1])
|
||
|
oid, err := parseOID(aliases, args[2:])
|
||
|
if err != nil {
|
||
|
return nil, withLine(err)
|
||
|
}
|
||
|
if _, ok := aliases[aliasName]; ok {
|
||
|
return nil, withLine(fmt.Errorf("duplicate name '%s'", aliasName))
|
||
|
}
|
||
|
aliases[aliasName] = oid
|
||
|
default:
|
||
|
return nil, withLine(fmt.Errorf("unknown directive '%s'", args[0]))
|
||
|
}
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
fields := strings.Split(line, ":")
|
||
|
if len(fields) < 2 || len(fields) > 3 {
|
||
|
return nil, withLine(errors.New("invalid field count"))
|
||
|
}
|
||
|
|
||
|
obj := object{name: nextName}
|
||
|
nextName = ""
|
||
|
|
||
|
var err error
|
||
|
obj.oid, err = parseOID(aliases, strings.Fields(fields[0]))
|
||
|
if err != nil {
|
||
|
return nil, withLine(err)
|
||
|
}
|
||
|
obj.encoded = encodeOID(obj.oid)
|
||
|
|
||
|
obj.shortName = strings.TrimSpace(fields[1])
|
||
|
if len(fields) == 3 {
|
||
|
obj.longName = strings.TrimSpace(fields[2])
|
||
|
}
|
||
|
|
||
|
// Long and short names default to each other if missing.
|
||
|
if len(obj.shortName) == 0 {
|
||
|
obj.shortName = obj.longName
|
||
|
} else {
|
||
|
obj.hasShortName = true
|
||
|
}
|
||
|
if len(obj.longName) == 0 {
|
||
|
obj.longName = obj.shortName
|
||
|
} else {
|
||
|
obj.hasLongName = true
|
||
|
}
|
||
|
if len(obj.shortName) == 0 || len(obj.longName) == 0 {
|
||
|
return nil, withLine(errors.New("object with no name"))
|
||
|
}
|
||
|
|
||
|
// If not already specified, prefer the long name if it has no
|
||
|
// spaces, otherwise the short name.
|
||
|
if len(obj.name) == 0 && strings.IndexRune(obj.longName, ' ') < 0 {
|
||
|
obj.name = sanitizeName(obj.longName)
|
||
|
}
|
||
|
if len(obj.name) == 0 {
|
||
|
obj.name = sanitizeName(obj.shortName)
|
||
|
}
|
||
|
obj.name = module + obj.name
|
||
|
|
||
|
// Check for duplicate names.
|
||
|
if _, ok := aliases[obj.name]; ok {
|
||
|
return nil, withLine(fmt.Errorf("duplicate name '%s'", obj.name))
|
||
|
}
|
||
|
if _, ok := shortNamesSeen[obj.shortName]; ok && len(obj.shortName) > 0 {
|
||
|
return nil, withLine(fmt.Errorf("duplicate short name '%s'", obj.shortName))
|
||
|
}
|
||
|
if _, ok := longNamesSeen[obj.longName]; ok && len(obj.longName) > 0 {
|
||
|
return nil, withLine(fmt.Errorf("duplicate long name '%s'", obj.longName))
|
||
|
}
|
||
|
|
||
|
// Allocate a NID.
|
||
|
nid, ok := nameToNID[obj.name]
|
||
|
if !ok {
|
||
|
nid = len(objs.byNID)
|
||
|
objs.byNID = append(objs.byNID, object{})
|
||
|
}
|
||
|
|
||
|
objs.byNID[nid] = obj
|
||
|
objs.nameToNID[obj.name] = nid
|
||
|
|
||
|
longNamesSeen[obj.longName] = struct{}{}
|
||
|
shortNamesSeen[obj.shortName] = struct{}{}
|
||
|
aliases[obj.name] = obj.oid
|
||
|
}
|
||
|
if err := scanner.Err(); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return objs, nil
|
||
|
}
|
||
|
|
||
|
func writeNumbers(path string, objs *objects) error {
|
||
|
out, err := os.Create(path)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
defer out.Close()
|
||
|
|
||
|
for nid, obj := range objs.byNID {
|
||
|
if len(obj.name) == 0 {
|
||
|
continue
|
||
|
}
|
||
|
if _, err := fmt.Fprintf(out, "%s\t\t%d\n", obj.name, nid); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func clangFormat(input string) (string, error) {
|
||
|
var b bytes.Buffer
|
||
|
cmd := exec.Command("clang-format")
|
||
|
cmd.Stdin = strings.NewReader(input)
|
||
|
cmd.Stdout = &b
|
||
|
cmd.Stderr = os.Stderr
|
||
|
if err := cmd.Run(); err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
return b.String(), nil
|
||
|
}
|
||
|
|
||
|
func writeHeader(path string, objs *objects) error {
|
||
|
var b bytes.Buffer
|
||
|
fmt.Fprintf(&b, `/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* This package is an SSL implementation written
|
||
|
* by Eric Young (eay@cryptsoft.com).
|
||
|
* The implementation was written so as to conform with Netscapes SSL.
|
||
|
*
|
||
|
* This library is free for commercial and non-commercial use as long as
|
||
|
* the following conditions are aheared to. The following conditions
|
||
|
* apply to all code found in this distribution, be it the RC4, RSA,
|
||
|
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||
|
* included with this distribution is covered by the same copyright terms
|
||
|
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||
|
*
|
||
|
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||
|
* the code are not to be removed.
|
||
|
* If this package is used in a product, Eric Young should be given attribution
|
||
|
* as the author of the parts of the library used.
|
||
|
* This can be in the form of a textual message at program startup or
|
||
|
* in documentation (online or textual) provided with the package.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions
|
||
|
* are met:
|
||
|
* 1. Redistributions of source code must retain the copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in the
|
||
|
* documentation and/or other materials provided with the distribution.
|
||
|
* 3. All advertising materials mentioning features or use of this software
|
||
|
* must display the following acknowledgement:
|
||
|
* "This product includes cryptographic software written by
|
||
|
* Eric Young (eay@cryptsoft.com)"
|
||
|
* The word 'cryptographic' can be left out if the rouines from the library
|
||
|
* being used are not cryptographic related :-).
|
||
|
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||
|
* the apps directory (application code) you must include an acknowledgement:
|
||
|
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG `+"``"+`AS IS'' AND
|
||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||
|
* SUCH DAMAGE.
|
||
|
*
|
||
|
* The licence and distribution terms for any publically available version or
|
||
|
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||
|
* copied and put under another distribution licence
|
||
|
* [including the GNU Public Licence.] */
|
||
|
|
||
|
/* This file is generated by crypto/obj/objects.go. */
|
||
|
|
||
|
#ifndef OPENSSL_HEADER_NID_H
|
||
|
#define OPENSSL_HEADER_NID_H
|
||
|
|
||
|
#include <openssl/base.h>
|
||
|
|
||
|
#if defined(__cplusplus)
|
||
|
extern "C" {
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/* The nid library provides numbered values for ASN.1 object identifiers and
|
||
|
* other symbols. These values are used by other libraries to identify
|
||
|
* cryptographic primitives.
|
||
|
*
|
||
|
* A separate objects library, obj.h, provides functions for converting between
|
||
|
* nids and object identifiers. However it depends on large internal tables with
|
||
|
* the encodings of every nid defined. Consumers concerned with binary size
|
||
|
* should instead embed the encodings of the few consumed OIDs and compare
|
||
|
* against those.
|
||
|
*
|
||
|
* These values should not be used outside of a single process; they are not
|
||
|
* stable identifiers. */
|
||
|
|
||
|
|
||
|
`)
|
||
|
|
||
|
for nid, obj := range objs.byNID {
|
||
|
if len(obj.name) == 0 {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
if obj.hasShortName {
|
||
|
fmt.Fprintf(&b, "#define SN_%s \"%s\"\n", obj.name, obj.shortName)
|
||
|
}
|
||
|
if obj.hasLongName {
|
||
|
fmt.Fprintf(&b, "#define LN_%s \"%s\"\n", obj.name, obj.longName)
|
||
|
}
|
||
|
fmt.Fprintf(&b, "#define NID_%s %d\n", obj.name, nid)
|
||
|
|
||
|
// Although NID_undef does not have an OID, OpenSSL emits
|
||
|
// OBJ_undef as if it were zero.
|
||
|
oid := obj.oid
|
||
|
if nid == 0 {
|
||
|
oid = []int{0}
|
||
|
}
|
||
|
if len(oid) != 0 {
|
||
|
var oidStr string
|
||
|
for _, val := range oid {
|
||
|
if len(oidStr) != 0 {
|
||
|
oidStr += ","
|
||
|
}
|
||
|
oidStr += fmt.Sprintf("%dL", val)
|
||
|
}
|
||
|
|
||
|
fmt.Fprintf(&b, "#define OBJ_%s %s\n", obj.name, oidStr)
|
||
|
}
|
||
|
|
||
|
fmt.Fprintf(&b, "\n")
|
||
|
}
|
||
|
|
||
|
fmt.Fprintf(&b, `
|
||
|
#if defined(__cplusplus)
|
||
|
} /* extern C */
|
||
|
#endif
|
||
|
|
||
|
#endif /* OPENSSL_HEADER_NID_H */
|
||
|
`)
|
||
|
|
||
|
formatted, err := clangFormat(b.String())
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return ioutil.WriteFile(path, []byte(formatted), 0666)
|
||
|
}
|
||
|
|
||
|
// TODO(davidben): Replace this with sort.Slice once Go 1.8 is sufficiently
|
||
|
// common.
|
||
|
type nidSorter struct {
|
||
|
nids []int
|
||
|
objs *objects
|
||
|
cmp func(a, b object) bool
|
||
|
}
|
||
|
|
||
|
func (a nidSorter) obj(i int) object { return a.objs.byNID[a.nids[i]] }
|
||
|
func (a nidSorter) Len() int { return len(a.nids) }
|
||
|
func (a nidSorter) Swap(i, j int) { a.nids[i], a.nids[j] = a.nids[j], a.nids[i] }
|
||
|
func (a nidSorter) Less(i, j int) bool { return a.cmp(a.obj(i), a.obj(j)) }
|
||
|
|
||
|
func sortNIDs(nids []int, objs *objects, cmp func(a, b object) bool) {
|
||
|
sort.Sort(&nidSorter{nids, objs, cmp})
|
||
|
}
|
||
|
|
||
|
func writeData(path string, objs *objects) error {
|
||
|
var b bytes.Buffer
|
||
|
fmt.Fprintf(&b, `/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* This package is an SSL implementation written
|
||
|
* by Eric Young (eay@cryptsoft.com).
|
||
|
* The implementation was written so as to conform with Netscapes SSL.
|
||
|
*
|
||
|
* This library is free for commercial and non-commercial use as long as
|
||
|
* the following conditions are aheared to. The following conditions
|
||
|
* apply to all code found in this distribution, be it the RC4, RSA,
|
||
|
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||
|
* included with this distribution is covered by the same copyright terms
|
||
|
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||
|
*
|
||
|
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||
|
* the code are not to be removed.
|
||
|
* If this package is used in a product, Eric Young should be given attribution
|
||
|
* as the author of the parts of the library used.
|
||
|
* This can be in the form of a textual message at program startup or
|
||
|
* in documentation (online or textual) provided with the package.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions
|
||
|
* are met:
|
||
|
* 1. Redistributions of source code must retain the copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in the
|
||
|
* documentation and/or other materials provided with the distribution.
|
||
|
* 3. All advertising materials mentioning features or use of this software
|
||
|
* must display the following acknowledgement:
|
||
|
* "This product includes cryptographic software written by
|
||
|
* Eric Young (eay@cryptsoft.com)"
|
||
|
* The word 'cryptographic' can be left out if the rouines from the library
|
||
|
* being used are not cryptographic related :-).
|
||
|
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||
|
* the apps directory (application code) you must include an acknowledgement:
|
||
|
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG `+"``"+`AS IS'' AND
|
||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||
|
* SUCH DAMAGE.
|
||
|
*
|
||
|
* The licence and distribution terms for any publically available version or
|
||
|
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||
|
* copied and put under another distribution licence
|
||
|
* [including the GNU Public Licence.] */
|
||
|
|
||
|
/* This file is generated by crypto/obj/objects.go. */
|
||
|
|
||
|
|
||
|
`)
|
||
|
|
||
|
fmt.Fprintf(&b, "#define NUM_NID %d\n", len(objs.byNID))
|
||
|
|
||
|
// Emit each object's DER encoding, concatenated, and save the offsets.
|
||
|
fmt.Fprintf(&b, "\nstatic const uint8_t kObjectData[] = {\n")
|
||
|
offsets := make([]int, len(objs.byNID))
|
||
|
var nextOffset int
|
||
|
for nid, obj := range objs.byNID {
|
||
|
if len(obj.name) == 0 || len(obj.encoded) == 0 {
|
||
|
offsets[nid] = -1
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
offsets[nid] = nextOffset
|
||
|
nextOffset += len(obj.encoded)
|
||
|
fmt.Fprintf(&b, "/* NID_%s */\n", obj.name)
|
||
|
for _, val := range obj.encoded {
|
||
|
fmt.Fprintf(&b, "0x%02x, ", val)
|
||
|
}
|
||
|
fmt.Fprintf(&b, "\n")
|
||
|
}
|
||
|
fmt.Fprintf(&b, "};\n")
|
||
|
|
||
|
// Emit an ASN1_OBJECT for each object.
|
||
|
fmt.Fprintf(&b, "\nstatic const ASN1_OBJECT kObjects[NUM_NID] = {\n")
|
||
|
for nid, obj := range objs.byNID {
|
||
|
if len(obj.name) == 0 {
|
||
|
fmt.Fprintf(&b, "{NULL, NULL, NID_undef, 0, NULL, 0},\n")
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
fmt.Fprintf(&b, "{\"%s\", \"%s\", NID_%s, ", obj.shortName, obj.longName, obj.name)
|
||
|
if offset := offsets[nid]; offset >= 0 {
|
||
|
fmt.Fprintf(&b, "%d, &kObjectData[%d], 0},\n", len(obj.encoded), offset)
|
||
|
} else {
|
||
|
fmt.Fprintf(&b, "0, NULL, 0},\n")
|
||
|
}
|
||
|
}
|
||
|
fmt.Fprintf(&b, "};\n")
|
||
|
|
||
|
// Emit a list of NIDs sorted by short name.
|
||
|
var nids []int
|
||
|
for nid, obj := range objs.byNID {
|
||
|
if len(obj.name) == 0 || len(obj.shortName) == 0 {
|
||
|
continue
|
||
|
}
|
||
|
nids = append(nids, nid)
|
||
|
}
|
||
|
sortNIDs(nids, objs, func(a, b object) bool { return a.shortName < b.shortName })
|
||
|
|
||
|
fmt.Fprintf(&b, "\nstatic const unsigned kNIDsInShortNameOrder[] = {\n")
|
||
|
for _, nid := range nids {
|
||
|
fmt.Fprintf(&b, "%d /* %s */,\n", nid, objs.byNID[nid].shortName)
|
||
|
}
|
||
|
fmt.Fprintf(&b, "};\n")
|
||
|
|
||
|
// Emit a list of NIDs sorted by long name.
|
||
|
nids = nil
|
||
|
for nid, obj := range objs.byNID {
|
||
|
if len(obj.name) == 0 || len(obj.longName) == 0 {
|
||
|
continue
|
||
|
}
|
||
|
nids = append(nids, nid)
|
||
|
}
|
||
|
sortNIDs(nids, objs, func(a, b object) bool { return a.longName < b.longName })
|
||
|
|
||
|
fmt.Fprintf(&b, "\nstatic const unsigned kNIDsInLongNameOrder[] = {\n")
|
||
|
for _, nid := range nids {
|
||
|
fmt.Fprintf(&b, "%d /* %s */,\n", nid, objs.byNID[nid].longName)
|
||
|
}
|
||
|
fmt.Fprintf(&b, "};\n")
|
||
|
|
||
|
// Emit a list of NIDs sorted by OID.
|
||
|
nids = nil
|
||
|
for nid, obj := range objs.byNID {
|
||
|
if len(obj.name) == 0 || len(obj.encoded) == 0 {
|
||
|
continue
|
||
|
}
|
||
|
nids = append(nids, nid)
|
||
|
}
|
||
|
sortNIDs(nids, objs, func(a, b object) bool {
|
||
|
// This comparison must match the definition of |obj_cmp|.
|
||
|
if len(a.encoded) < len(b.encoded) {
|
||
|
return true
|
||
|
}
|
||
|
if len(a.encoded) > len(b.encoded) {
|
||
|
return false
|
||
|
}
|
||
|
return bytes.Compare(a.encoded, b.encoded) < 0
|
||
|
})
|
||
|
|
||
|
fmt.Fprintf(&b, "\nstatic const unsigned kNIDsInOIDOrder[] = {\n")
|
||
|
for _, nid := range nids {
|
||
|
obj := objs.byNID[nid]
|
||
|
fmt.Fprintf(&b, "%d /* ", nid)
|
||
|
for i, c := range obj.oid {
|
||
|
if i > 0 {
|
||
|
fmt.Fprintf(&b, ".")
|
||
|
}
|
||
|
fmt.Fprintf(&b, "%d", c)
|
||
|
}
|
||
|
fmt.Fprintf(&b, " (OBJ_%s) */,\n", obj.name)
|
||
|
}
|
||
|
fmt.Fprintf(&b, "};\n")
|
||
|
|
||
|
formatted, err := clangFormat(b.String())
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return ioutil.WriteFile(path, []byte(formatted), 0666)
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
objs, err := readObjects("obj_mac.num", "objects.txt")
|
||
|
if err != nil {
|
||
|
fmt.Fprintf(os.Stderr, "Error reading objects: %s\n", err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
|
||
|
if err := writeNumbers("obj_mac.num", objs); err != nil {
|
||
|
fmt.Fprintf(os.Stderr, "Error writing numbers: %s\n", err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
|
||
|
if err := writeHeader("../../include/openssl/nid.h", objs); err != nil {
|
||
|
fmt.Fprintf(os.Stderr, "Error writing header: %s\n", err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
|
||
|
if err := writeData("obj_dat.h", objs); err != nil {
|
||
|
fmt.Fprintf(os.Stderr, "Error writing data: %s\n", err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
}
|