
		       The New TIS/MOSS Database
		       -------------------------

		        Updated: 15 March 1994


Table of Contents
-----------------

Overview
Tag/Value Pairs
Example User Records
Private Key Files
Security Model
Database/User Record Access Routines

			       Overview
			       --------

The TIS/MOSS database has been redesigned to provide flexible,
efficient access for smaller, individual databases and easily provide
support for the draft MOSS standard, multiple databases, and alternate
cryptographic devices.

The TIS/MOSS database is primarily embodied in a single,
human-readable, ASCII text database file. This file contains all
public information.  The only information not in the database file are
private keys; instead, an access method and associated parameters are
indicated for each private key.  Multiple databases are as easy as
multiple ASCII files.

Database files contain user records separated by one or more blank
lines.  User records are processed sequentially and some processing
will terminate with the first user record that satisfies given
requirements while other processing will continue through all user
records.  User records contain tag/value field pairs.  Each tag/value
pair starts on a new line with a colon separating the tag and the
value.  Tag/value lines may be wrapped for readability by inserting a
new line and then one or more white space characters on the
continuation line.  Tags are case-insensitive and unknown tags are
ignored.

All tags in a user record may occur at most once, except for the
"alias" tag, which may occur multiple times.  User records are
"anchored" by public key, so public keys and certificates
(well-dressed keys) must be unique throughout all user records.  This
is assumed, but not enforced.  Programs will likely operate only on
the first instance of a tag/value pair in a user record if it is
anything but the alias tag.

Some of the tag value pairs are redundant, but as long as the data is
consistent, fewer translations and decodings may be required for any
given processing.  To this end the software will always create
self-consistent user records.  For example, a user may have both
certificate and public-key fields, even though the certificate
contains the public key.  If redundant fields exist, consistency is
assumed, but not enforced.  Applications will likely operate on the
data easiest to handle for the processing at hand, so the results of
having inconsistent values may vary from application to application.


			   Tag/Value Pairs
			   ---------------

Following are the currently defined tags and the meanings and formats
of their values:

  public-key:

        The printably encoded, ASN.1 encoded public key.  Must match
	public key in certificate if certificate exists.  This
	tag/value pair 	"anchors" the user record and musr be present.
	Records without this pair may be ignored.

  trusted: 

	Alias of a user record placing trust in this public key,
	followed by a comma and the MOSS signature (same contents as
	MIC-Info field) by that user of the rest of this user record.
	Indicates a trusted user record. This field provides the basis
	for all trust models in TIS/MOSS.

  certificate:

	The printably encoded, ASN.1 encoded certificate.  Must
	contain same information as in broken-out fields (public-key,
	subject-name, issuer-name, serial-number).

  crl:

	The printably encoded, ASN.1 encoded CRL that has been signed
	by the private key associated with this user record's public
	key.

  subject-name:

	User friendly distinguished name of user as extracted from
	certificate subject field or DN name form.  Must match
	certificate subject distinguished name, if certificate exists.
	
  issuer-name:

        User friendly distinguished name of issuer extracted from
	certificate or ISN name form.  Must match certificate issuer
	name, if certificate exists.

  serial-number:

	Hexadecimal serial number extracted from certificate or ISN
	name form.  Must match certificate serial number, if
	certificate exists.

  id-dn-keyid:
  id-en-keyid:
  id-str-keyid:

	The keyid contents of any of the non-unique (DN, EN, STR) name
	forms as received in an ID header.  A hexadeximal number used
        to make a name form unique for a user.  At most one of each
        tag per user record.  It is possible that there may be
	duplicates between distinct users.

  id-dn:
  id-en:
  id-str:

	The non-keyid contents of any of the non-unique (DN, EN, STR)
	name forms as received in an ID header.  At most one of each
	tag per user. It is possible that there may be duplicates
	between distinct users.

  private-key-access: 

  	Method for accessing private key.  The only currently defined
	method is "file" which mandates a private-key tag/value pair
	containing the rooted path to the file containing the private
	key.

  private-key: 

	Additional information necessary to use private key based on
	private-key-access method.  If the private key access method
	is "file", the value for private-key is the name of the file
	containing the private key. If the name is not fully
	qualified, the value of the "directory" tailorable tag/value
	pair is prepended.  If the name is still unqualified, the
	value of the "HOME" environement variable is prepended.

  alias:

	A token to identify a user record.  There can be more than one
	per user record.  The same alias can be used in multiple user
	records to identify a group of users, but there are times when
	only an alias that identifies a single user record will be
	useful.  When a single user record containing the alias is
	needed, the first one in the public file is used.  Two special
	aliases are "me" and "sig-user", which indicate user records
	that are the user's and the default user record to use for
	signatures, respectively.

  display:

	A message meaningful to you that will be displayed to identify
        this user record.  If a display tag/value pair is not
  	prestent, other information in the user record will be
	displayed.


			 Example User Records
			 --------------------

Below are some sample user records you might see in a TIS/MOSS
database.  Blank lines and lines beginning with a pound sign (#) are
considered record terminators, but are otherwise ignored. Lines
beginning with a dollar sign are special directives, of which $include
is the only one currently defined.  $include followed by white space
and a file name causes the named file to be read from at that point
and then reading is resumed in the "current" file once the included
file has been exhausted.  $include lines can be nested up to 5 deep.

# The first three are real user records.

certificate:MIICBjCCAW8CAQYwDQYJKoZIhvcNAQECBQAwUzELMAkGA1UEBhMCVVMxCzAJ
 BgNVBAgTAk1EMSQwIgYDVQQKExtUcnVzdGVkIEluZm9ybWF0aW9uIFN5c3RlbXMxETAPBgN
 VBAsTCEdsZW53b29kMB4XDTkzMDYwMTAyMzcxNloXDTk1MDYwMTAyMzcxNlowbTELMAkGA1
 UEBhMCVVMxCzAJBgNVBAgTAk1EMSQwIgYDVQQKExtUcnVzdGVkIEluZm9ybWF0aW9uIFN5c
 3RlbXMxETAPBgNVBAsTCEdsZW53b29kMRgwFgYDVQQDEw9NYXJrIFMuIEZlbGRtYW4wdzAK
 BgRVCAEBAgIDAANpADBmAmEAonNp8hNQAbmYl+bkjZM8fNgW/NZfpWOgW7qfchZ4V0iTDoX
 WZwm4asyIBITboRuA7jtYiangImJGKhzCg9vm6mL0bbOd9S+CKC9cMgbTwPq3o0LmCZYns+
 9+bTQ9nHxhAgEDMA0GCSqGSIb3DQEBAgUAA4GBAFsK7oxsiHU805pzrFOC8s1Kf9GOSaj7y
 iN6RjiKscYoaWrmCJgskV2eH9ZYxTY2SHyQKo4cZz6LUVWZbt4Q0VzedNwsp5Trxi3jOyju
 ZCXQ1KGjmgXCQCX1zoTptRaEIvgIqrLQEEQxMVhkV0oGhrYwjA/c2tn7xW6KuZmVe3rj
public-key:MHcwCgYEVQgBAQICAwADaQAwZgJhAKJzafITUAG5mJfm5I2TPHzYFvzWX6Vjo
 Fu6n3IWeFdIkw6F1mcJuGrMiASE26EbgO47WImp4CJiRiocwoPb5upi9G2znfUvgigvXDIG
 08D6t6NC5gmWJ7Pvfm00PZx8YQIBAw==
issuer-name:/Country Name=US/State or Province Name=MD/Organization Name
 =Trusted Information Systems/Organizational Unit Name=Glenwood/
serial-number:06
subject-name:/Country Name=US/State or Province Name=MD/Organization Nam
 e=Trusted Information Systems/Organizational Unit Name=Glenwood/Common
 Name=Mark S. Feldman/
alias:feldman@tis.com
alias:feldman

# Notice how small the public key really is.  tester (below) has a
# 600-bit key.

alias:tester
alias:sig-user
alias:me
private-key-access:file
private-key:/floppy/.mykey
public-key:MGQwCgYEVQgBAQICAlgDVgAwUwJMANgBIXKJqqQebh64mQH+O2gUybjuzjsJc
 W6LyVfnNTM4fBGOE5ct73+XtZsa6CwiVU00NOfcCGDHHzMNojnsxXMTT/clCQ7VEkoRqQID
 AQAB

# Just for fun, include another database
$include /floppy/personal-db
# and when it's contents are exhausted, we pick up here.

private-key-access:tessera
public-key:EMSQwIgYDVQQKExtUcnVzdGVkIEluZm9ybWF0aW9uIFN5c3RlbXMxETA33334
 VBAsTCEdsZW53b29kMB4XDTkzMDYwMTAyMzcxNloXDTk1MDYwMTAyMzcxNlowbTELMAkGA1
 UEBhMCVVMxCzAJBgNVBAgTAk1EMSQwIgYDVQQKExtUcnVzdGVkIEluZm9ybWF0aW9uIFN5c
 3RlbXMxETAPBgNVBAsTCEdsZW53b29kMRgwFgYDVQQDEw9NYXJrIFMuIEZlbGRtYW4wdzAK
trusted:feldman,RSA-MD5,RSA,WLuJn3HFcKrqgzWCf0pRl8m7/A2HbfRvaS8/bi40Yp6p
 xfzIwIVHui6k4U49ZE8y4H6E8mvyeH2Nhf8H1aDyPcN+BzV7cO+nQbbq4lZOGerdJywxVim
 TyeVVoe ZiNt5


			  Private Key Files
			  -----------------

Private key files, when they exist consist of a byte indicating
whether or not the rest of the file is encrypted, followed by the
16-byte MD5 hash of the private key, followed by two bytes indicating
the length of the printably encoded, ASN.1 encoded private key, and
the printably encoded, ASN.1 encoded private key.  The first byte of
the file has the following meanings:

  0x00:  Unencrypted private key.
  0x01:  Remaining contents encrypted (with DES).


			    Security Model
			    --------------

A combination of UNIX file permissions (discretionary access control)
and cryptography protect databases and private keys.

File permissions are the first line of defense.  The default database
is $HOME/.mossdb and it is created with permissions 0644.  This
default permits the user to read and write the file and everyone else
to read it.  Permission to access a database file can be modified by
the user by changing the permissions on the file after it is created,
or changing the permissions on the directory in which the database
resides or any of the directories above it.

Private key files are created when and where the user specified when a
key pair is generated or imported.  Private key files are always
generated with the permission 0600.  This allows for read and write by
the user, but no one else.  Private keys themselves may then be
encrypted in the private key file using DES or triple-DES (future).

In addition to having direct access to private keys, the database
provides for additional private key access methods (e.g., smart cards)
which will provide their own authentication and private key
cryptographic functions without allowing the user or anyone else
direct access to the private key.


		 Database/User Record Access Routines
		 ------------------------------------

The new database format facilitates sequential access.  A set of
routines a la the password file access routines (e.g., getpwent and
setpwent) are used to select public files and access user records.
Additional routines are used to process the tag/value pairs in a user
record.

Internally, user records are AVs (char **), containing alternating
tags and values.  Since every tag has an associated value, there
should always be an even number of CPs in each AV.  

Low Level (comparable to old lib/cfile, lib/data, and lib/hash) routines:

  int set_indexfile(char *name)

	Closes currently open indexfile, if such exists, and sets name
	of indexfile for gets.  Returns OK/NOTOK.

	The TIS/MOSS initialization routine, moss_init(), calls
	set_indexfile with the default database name, the tailored
	database name, or the database name provided on the command
	line of the program.

  int rewind_indexfile()

	Rewinds current indexfile, opening file if necessary.  Returns
	OK/NOTOK.

  char **get_indexfile()

	Returns next user record as an AV from indexfile or NULLVP.
	Uses rewind_indexfile() to open the file if it is not already
	open.

  int end_indexfile()

	Closes get indexfile.  Returns OK.

  int set_put_indexfile(char *name)

	Sets name of indexfile for future puts and closes previously
	opened put indexfile if open.  Returns OK/NOTOK.

  int put_indexfile(char **av)

	Adds a record (AV) to the current put indexfile.  Creates the
	file if it does not exist and truncates it otherwise.  Returns
	OK/NOTOK.

  int end_put_indexfile()

	Closes put indexfile.  Returns OK.

  char **tag_user (char **user, char *tag) 

	Returns a pointer (AV) to the first tag in the user record
	<user> with the name <tag> or NULLVP if there is no such tag.

  char **tagval_user (char **user, char *tag, char *value)  

	Returns a pointer (AV) to the tag in <user> with the name
	<tag> and value <value> or NULLCP.

  char **get_tv_user (char *tag, char *value) 

	Returns a pointer to the next user record (AV) in the
	current index file containing the requested tag/value pair
	NULLCP.

  char **get_tvt_user (char **template)  

	Returns a pointer to the next user record (AV) in the current
	index file containing all of the tag/value pairs present in
	<template>.  Useful for looking up a user by several possible
	tags.  E.g., given a certificate, you can search based on the
	certificate, public key, or issuer name/serial number.

  char *key_user (char **user)

	Returns a pointer to a character string containing the
	printably encoded, ASN.1 encoded public key from the user
	record or NULLCP.  The public-key and certificate tag/value
	pairs are searched in that order.
 
  char **merge_user(char **user, char **av)

	Returns a pointer to a user record which has had the tag/value
	pairs in AV added to or replacing those in the supplied user
	record.  This routine knows that only the tag "alias" may
	appear more than once in a user record.

  char **explode_cert (char *cert_value)

	Given the value portion of a "certificate" tag/value pair,
	return a user record (AV) containing all derived tag/value
	pairs, including "certificate", "public-key", "issuer-name",
	"serial-number", and "subject-name".

  int update_indexfile (char **remove, char ** add)

	The current index file is updated by removing user records
	matching <remove> and adding/replacing user records matching
	<add>.  A user record matches either or both of <remove> and
	<add> if its public-key matches the public-key in <remove> or
	<add>.  If a public key is not present in <remove> or <add> it
	is ignored.

  struct user_list *alloc_ul()

	Return a pointer to a newly created, empty user list.  User
	lists are used to maintain a list of user records (AVs).  The
	definition of a user_list is:

	struct user_list {
	    char **user;
	    struct user_list *next;
	};

  int free_ul (ul)

	Frees a user list. 

  int free_uls (ul)

	Frees all user list records in a list.
