Friday, March 9, 2018

BSD Kernel Hacking - Part 2 (character pseudo-devices)

Continuing on from the last post, I now tackle character devices. It turns out that OpenBSD is quite a lot different than FreeBSD in the way that devices are registered. To begin, I need to set up a cdevsw entry for the new device. Rather than defining the struct directly in the implementation code, it is implemented via a macro which is called in the cdevsw struct definition in sys/arch/amd64/amd64/conf.c

As opposed to FreeBSD, the cdevsw structs are built out by a macro, this macro will take the number of devices being initialized, and the name of the module passed to it (e.g. "cdev_example_init(1, example)") and fill out struct cdevsw to point to the appropriate functions via name concatenation (e.g. the open function will be registered as exampleopen).

I begin by adding a cdev_example_init macro to sys/sys/conf.h, then call the macro within the cdevsw[] array in sys/arch/amd64/amd64/conf.c. Also, while I'm in here, I add a call to the cdev_decl() macro. This should take care of the cdevsw setup portion of the code.

From there, I add example.c under sys/dev/ and build out basic open, close, read, and write functions for it, and add it to files.conf. Much to my surprise, after fixing a few compile errors for missing headers, the kernel compiles and installs fine. Once the machine had booted into my new kernel, I ran a "doas mknod /dev/example c 98 0" to create a node for the device in /dev. In this case, 98 was the position in the cdevsw[] array where my call to cdev_exampl_init landed. In OpenBSD, the major node number is simply an index into the cdevsw array.

I had to switch from using copystr to uiomove in order to get I/O working properly, but once I did, the basic interface code worked fine.

Finally, I decided to work with the MAKEDEV script to ensure that my device would be present in a release, if I so chose to make one. The script required me to add a new case for "example)" with a call to the M function and a few parameters to set the device node name, Major/Minor numbers, permissions, and ownership. In order for etc/etc.amd64/MAKEDEV to be copied to /dev by sysmerge, I had to do a full build of the system. This is a bit time consuming, and there might be a better way, but it worked for my immediate purposes.

Friday, March 2, 2018

BSD Kernel Hacking - Part 1 (Intro/Syscalls)

Lately I've been reading through Designing BSD Rootkits by Joseph Kong. The book was released back in 2007, and is a treasure trove of information about BSD kernel hacking.

Unfortunately, much has changed since it was released, and the book was written with FreeBSD in mind, while I am more of an OpenBSD fan. I am hoping to start another multipart series based on exercises in this book. First off I will be going through the code in this book as I read, and updating it to run on FreeBSD 11.1. After that, I intend to work on hacking this code into the OpenBSD kernel, which is a little more difficult, as OpenBSD does not support Loadable Kernel Modules anymore.

The first chapter begins with a simple module that will print "Hello World!" on load, and "Goodbye, Cruel World!" on unload. This little experiment works just find out of the box on FreeBSD 11.1. Since OpenBSD doesn't have a LKM system, and this module does nothing without being loaded, porting it over isn't worthwhile.

One lesson of note from this experiment, is that uprintf() is used for printing to userspace, while regular ole' printf() will print to the system console (viewable with dmesg).

The second example in the book expands on the first to create a new syscall. This is where things start to go sideways -- my first attempts using code from the book fail to compile:

root@freebsd-dev:~/syscall # make
Warning: Object directory not changed from original /root/syscall
cc -O2 -pipe  -fno-strict-aliasing -Werror -D_KERNEL -DKLD_MODULE -nostdinc   -I. -I/usr/src/sys -fno-common  -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer  -MD  -MF.depend.sc_example.o -MTsc_example.o -mcmodel=kernel -mno-red-zone -mno-mmx -mno-sse -msoft-float  -fno-asynchronous-unwind-tables -ffreestanding -fwrapv -fstack-protector -Wall -Wredundant-decls -Wnested-externs -Wstrict-prototypes  -Wmissing-prototypes -Wpointer-arith -Winline -Wcast-qual  -Wundef -Wno-pointer-sign -D__printf__=__freebsd_kprintf__  -Wmissing-include-dirs -fdiagnostics-show-option  -Wno-unknown-pragmas  -Wno-error-tautological-compare -Wno-error-empty-body  -Wno-error-parentheses-equality -Wno-error-unused-function  -Wno-error-pointer-sign -Wno-error-shift-negative-value -Wno-error-address-of-packed-member  -mno-aes -mno-avx  -std=iso9899:1999 -c sc_example.c -o sc_example.o
sc_example.c:48:1: error: use of undeclared identifier 'AUE_NULL'
SYSCALL_MODULE(sc_example, &offset, &sc_example_sysent, load, NULL);
^
/usr/src/sys/sys/sysent.h:204:43: note: expanded from macro 'SYSCALL_MODULE'
        evh, arg, offset, new_sysent, { 0, NULL, AUE_NULL }     \
                                                 ^
1 error generated.
*** Error code 1

Stop.
make: stopped in /root/syscall

This issue turned out to be caused by missing definitions in sys/sysproto.h. Once the missing header is included, the kernel module builds and loads fine, but the example interface code refuses to find the module. I modified the interface a bit to add error handling and check errno on the call to modfind() and found that it was returning an ENOENT. A bit of experimentation later, I discovered (via kldstat -v) that the actual name of sc_example was "sys/sc_example", not just "sc_example".

Next, I make an attempt to install a syscall into OpenBSD. This is a little more tricky due to a lack of LKMs. First, I create a file with a syscall function in it at sys/kern/sys_example.c. This syscall function is following the same prototype as all other OpenBSD syscalls, which is similar, but slightly different than FreeBSD. The syscall function simply outputs "proto wuz here" to the system console. 

From there, I found an unimplemented syscall number in sys/kern/syscalls.master (241), and updated the master list to include my sys_example syscall and called "make syscalls" in sys/kern, then added kern/sys_example.c to sys/conf/files to make sure it is included in the build.

This operation led to chasing compiler errors around missing includes for a while, but after all of the required headers were included, I was able to do a standard kernel build following the directions in release(8). After reboot, I was able to call syscall 241 from Perl and have the kernel display my message in the system console:

[peter@dev ~]$ perl -e "syscall(241);"
[peter@dev ~]$ dmesg | tail -1

proto wuz here

Here is the code from sys/kern/sys_example.c:


My final challenge for this post is to make the function behave the same as the example in the BSD Rootkit book, by accepting a string as an argument to the syscall and printing that to the console. I had to update my entry in syscalls.master to include the new argument, and include sys/syscallargs.h as well as a few other various headers. From there, the operation is almost identical to FreeBSD, except that a macro is used to access the arguments from their structure:



And the output from calling the syscall:

[peter@dev ~]$ perl -e '$str = "this is an OpenBSD syscall";' -e 'syscall(241, $str);'
[peter@dev ~]$ dmesg | tail -1

proto says: this is an OpenBSD syscall.

I obviously have some learning to do regarding code management in CVS, as my changes broke a bunch of the change/copyright information inside the files that were modified. I'm not too worried about it for the time being, as I don't intend to submit these changes upstream.

I did a little more code cleanup, and here is the final result:

If anyone finds anything that I've done wrong here, please feel free to yell at me about it in the comments.


References:

Designing BSD Rootkits: An Introduction to Kernel Hacking
by Joseph Kong
http://a.co/eSG5wWX

FAQ 5 - Building the System From Source
https://www.openbsd.org/faq/faq5.html

release(9)
https://man.openbsd.org/release

syscall(9)
https://man.openbsd.org/man9/syscall.9

Friday, April 15, 2016

Basic Communications Security Part 2 - password-store

When we last spoke about encryption, I covered nonrepudiation and the subject of signing.  Today, I will be showing a little less theory and more practical usage of GPG -- keeping your passwords safe.  I will be covering the use of our fancy new encryption key with pass (https://passwordstore.org).  My example machine today will be a shiny new OpenBSD 5.9 box, however the process is largely the same in Linux, et. al.

$ doas pkg_add -v password-store
doas (peter@devenv.my.domain) password:
Update candidates: quirks-2.197 -> quirks-2.197
quirks-2.197 signed on 2016-02-26T22:06:23Z
password-store-1.6.5:base64-1.5: ok
password-store-1.6.5:colortree-1.7.0: ok
password-store-1.6.5:xclip-0.12p0: ok
password-store-1.6.5:gnugetopt-1.1.6: ok
password-store-1.6.5:pwgen-2.07p2: ok
File /etc/bash_completion.d/pass-bash-completion.sh could not be installed:
        No such file or directory
password-store-1.6.5: ok
Extracted 375880 from 377728

That would be roughly equivalent to a 'sudo yum install pass', 'brew install pass', etc.  Now that pass is installed, we will go ahead and initialize it with our key:

$ pass init 86F22317

Password store initialized for 86F22317

Now pass has created a simple file structure for us, and will store passwords inside GPG encrypted files within this file structure.  Let's start by creating a directory or two to categorize passwords, then we'll generate couple:

$ mkdir .password-store/websites
$ mkdir .password-store/ssh
$ pass
Password Store
|-- ssh
`-- websites
$ pass generate websites/facebook 26
The generated password for websites/facebook is:
D#)y=[fehkr`BRZJcrHFbA^8"Y
$ pass generate ssh/peter@example.com 32
The generated password for ssh/peter@example.com is:
S_=zXyt}:5Y`VX|7al&FVTyG^jXGH`L3
$ pass
Password Store
|-- ssh
|   `-- peter@example.com
`-- websites
    `-- facebook

Password-store has now generated two passwords for us called facebook in the websites category, which is 26 characters long, and one called peter@example.com in the ssh category, which is 32 characters long (neither of these are my real passwords).

These passwords are stored, as mentioned above in GPG encrypted files:

$ ls -lR .password-store/
total 8
drwxr-xr-x  2 peter  peter  512 Apr 14 16:05 ssh
drwxr-xr-x  2 peter  peter  512 Apr 14 16:05 websites

.password-store/ssh:
total 4
-rw-------  1 peter  peter  611 Apr 14 16:05 peter@example.com.gpg

.password-store/websites:
total 4

-rw-------  1 peter  peter  605 Apr 14 16:05 facebook.gpg

The passwords can then be retrieved to either STDOUT or the clipboard (by adding the -c flag) using your GPG key:

$ pass websites/facebook

You need a passphrase to unlock the secret key for
user: "Peter Ezetta "
4096-bit RSA key, ID 647AF373, created 2016-04-04 (main key ID 86F22317)


D#)y=[fehkr`BRZJcrHFbA^8"Y

Notice that the encryption subkey is used here, not the main key, which I keep offline on a USB stick.  

Another great feature of pass is it's built in git integration, allowing for easy team sharing of password stores, distributing and keeping passwords in sync between multiple machines:

$ pass git init
Initialized empty Git repository in /home/peter/.password-store/.git/
[master (root-commit) d1daf83] Add current contents of password store.
 Committer: Peter Ezetta

 3 files changed, 1 insertion(+)
 create mode 100644 .gpg-id
 create mode 100644 ssh/peter@example.com.gpg
 create mode 100644 websites/facebook.gpg
[master bd983ce] Configure git repository for gpg file diff.
 Committer: Peter Ezetta

 1 file changed, 1 insertion(+)

 create mode 100644 .gitattributes

Password-store is more than capable of adding git remotes and the like, but I will leave that as an exercise to the reader.  Much more information is available from the project website at https://passwordstore.org.

In the next part of this article, I will be discussing the web of trust and key signing procedures.  Stay tuned!

Saturday, April 9, 2016

A Few Words About Nonrepudiation

Standard disclaimers apply.  I'm not a lawyer, this isn't legal advice.  My opinions don't represent my employer.  It's not my fault if you do something stupid and get in trouble.


In my previous post, I discussed getting a GPG keyring set up.  I intend to continue in that vein, and explain email crypto/signing, the web of trust, document protection, and a few other fun topics around communications security -- but first, I want to stop and take a moment to discuss nonrepudiation.

According to techtarget.com:
Nonrepudiation is the assurance that someone cannot deny something. Typically, nonrepudiation refers to the ability to ensure that a party to a contract or a communication cannot deny the authenticity of their signature on a document or the sending of a message that they originated.
GPG provides us with nonrepudiation via document signing.  Document signing is a fairly simple process.  Briefly, when a document is signed, a hash is taken of it's contents.  A hash is a "one-way" mathematical algorithm that will take (generally) text data as an input, and return a unique string of letters and numbers.  This algorithm will always generate the same output, given the same input.  Changing even one character of the input will result in a different output.  Hashes are "one-way" algorithms, in that there is no process (other than brute force) to derive the original document from the hash.  For example, here is a SHA256 hash of this blog-post thus far:
228b9c49367a740073866f77ff09363ff3dbf62eda194b2b8a5660fe5bb5802e
If you were to copy everything from the disclaimer at the beginning of the post through the ":" at the end of the last paragraph, and pass it through shasum -a 256, you should receive the same long string of numbers and letters that I pasted above.   After a hash of the document being signed is taken, it is encrypted with the author's private key.  This means that anyone who possesses the author's public key can decrypt the hash.  We have now accomplished two things:

  1. The hash proves that the document has not been modified in any way since it was signed.
  2. The ability to decrypt the hash with the author's public key proves that the document was signed by an individual possessing the author's private key.
This all seems great, so back to nonrepudiation -- I hate it when someone tries to say they never told me something when I have evidence that they did.  Let's look at an illustrative example.

Alice sends an (unsigned) email to Bob, approving a new project.  Bob begins work on the project, but ultimately fails to deliver.  The business questions Bob as to why he "wasted" company funds on his failed project, so he produces the letter from Alice approving it.  The business then approaches Alice, who immediately denies sending the email.  We are now in a position of he-said/she-said.  Bob claims Alice sent the email, Alice claims that Bob forged it.

If Alice had signed the original email, GPG would have provided nonrepudiation -- Alice could have no longer denied that she sent the email to Bob.

Many sources (the manual linked in the previous article, for instance) recommend signing all emails all the time.  I would, however, encourage the reader to think about their own situation before deciding to sign all emails all the time.  In a business setting, it may be appropriate to implement a policy mandating that all emails are signed.  In a professional setting, we are expected to be accountable for what we say.  There are other situations, however, in which nonrepudiation may not be desirable.

Nonrepudiation is a double-edged sword.  By demanding signing of others, you gain assurances that they are, indeed, the author of what you are reading.  By signing documents yourself, you are irrefutably certifying that you wrote them.  It all boils down to one thing, really -- don't sign anything you wouldn't want to say under oath.  In the event your communications came before a court, it would be almost impossible to claim that you weren't the author.  This is especially true if there was continued use of the key after the communication was sent, as this shows that the key was under your control, and you had no suspicion of compromise (or else you would have issued that revocation certificate we made last article!).

To conclude -- mean what you say, say what you mean, and think before you sign documents.

Friday, April 8, 2016

Basic Communications Security - Part 1

I've recently been helping a friend get set up with GPG.  Also, I've been switching my password management over to pass.

Through this process, I have found GPG to be fairly straight forward, but it may be a bit daunting for some without prior crypto experience.  In this short series, I am going to cover basic setup of GPG for encryption and signing.  This keypair will consist of subkeys with an offline private master.  Once we have a working and secure GPG setup, I will move on to cover password management with pass, as well as GPG based authentication, and ultimately using hardware GPG tokens.

Hopefully this series will be useful to some.  As always, I welcome comments, questions, and corrections.

Part I - Key Generation

Note:  The example text was sourced from several different key operations on several different keys.  The key IDs and fingerprints in the example text may or may not correspond to valid and active keys.  My key can be retrieved from sks-keyservers, and it's ID is 86F22317.  Please use this key if you need to contact me.

For the sake of paranoia, I will be generating a master key on removable storage.  This key will be used to create subkeys for encryption, signing, and authentication, and it will be stored on removable storage in a safe.  To begin, you will need some clean removable media.  I am using OS X, so my media will be mounted at /Volumes/UNTITLED\ 1/.  Feel free to correct this path as appropriate for your environment.

First we will generate the key on the USB storage:

$ gpg --homedir /Volumes/UNTITLED\ 1/ --expert --gen-key

I use expert in this case to open up the option of setting custom capabilities for my keypair.  By default, GPG will generate a key that can sign and certify with a separate subkey that can encrypt.  I chose to create a master key that could only certify with subkeys that could encrypt and sign:

$ gpg --homedir /Volumes/UNTITLED\ 1/ --expert --gen-key
gpg: WARNING: unsafe permissions on homedir `/Volumes/UNTITLED\ 1/'
gpg (GnuPG) 1.4.20; Copyright (C) 2015 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gpg: keyring `/Volumes/UNTITLED\ 1/secring.gpg' created
gpg: keyring `/Volumes/UNTITLED\ 1/pubring.gpg' created
Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
Your selection? 8

Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Sign Certify Encrypt

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? s

Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Certify Encrypt

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? e

Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Certify

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? q
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
        = key expires in n days
      w = key expires in n weeks
      m = key expires in n months
      y = key expires in n years
Key is valid for? (0) 4y
Key expires at Tue Apr  7 11:05:27 2020 PDT
Is this correct? (y/N) y

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
    "Heinrich Heine (Der Dichter) "

Real name: Peter H. Ezetta
Email address: protocall7@sdf.org
Comment:
You selected this USER-ID:
    "Peter H. Ezetta "

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
You need a Passphrase to protect your secret key.

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
.................+++++
.+++++
gpg: /Volumes/UNTITLED\ 1/trustdb.gpg: trustdb created
gpg: key 86F22317 marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2020-04-04
pub   4096R/86F22317 2016-04-08 [expires: 2020-04-07]
      Key fingerprint = E1D3 330D 0107 8360 5417  C337 33D5 14D6 86F2 2317
uid                  Peter H. Ezetta

At this point, I have generated a new certify only key pair that exists only on the USB stick.  Now I will edit the key to add UIDs and subkeys for encryption and signing:

$ gpg --homedir /Volumes/UNTITLED\ 1 --edit-key protocall7@sdf.org
gpg: WARNING: unsafe permissions on homedir `/Volumes/UNTITLED\ 1'
gpg (GnuPG) 1.4.20; Copyright (C) 2015 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

pub  4096R/DDC547B9  created: 2016-04-08  expires: 2020-04-07  usage: C
                     trust: ultimate      validity: ultimate
[ultimate] (1). Peter H. Ezetta

gpg> addkey
Key is protected.

You need a passphrase to unlock the secret key for
user: "Peter H. Ezetta "
4096-bit RSA key, ID DDC547B9, created 2016-04-08

Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
Your selection? 6
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
        = key expires in n days
      w = key expires in n weeks
      m = key expires in n months
      y = key expires in n years
Key is valid for? (0) 1y
Key expires at Sat Apr  8 11:12:15 2017 PDT
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
............+++++
.........................+++++

pub  4096R/DDC547B9  created: 2016-04-08  expires: 2020-04-07  usage: C
                     trust: ultimate      validity: ultimate
sub  4096R/3BCD5DA0  created: 2016-04-08  expires: 2017-04-08  usage: E
[ultimate] (1). Peter H. Ezetta

gpg> addkey
Key is protected.

You need a passphrase to unlock the secret key for
user: "Peter H. Ezetta "
4096-bit RSA key, ID DDC547B9, created 2016-04-08

Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
Your selection? 4
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
        = key expires in n days
      w = key expires in n weeks
      m = key expires in n months
      y = key expires in n years
Key is valid for? (0) 1y
Key expires at Sat Apr  8 11:12:43 2017 PDT
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
......+++++
.............+++++

pub  4096R/DDC547B9  created: 2016-04-08  expires: 2020-04-07  usage: C
                     trust: ultimate      validity: ultimate
sub  4096R/3BCD5DA0  created: 2016-04-08  expires: 2017-04-08  usage: E
sub  4096R/A5FA0D33  created: 2016-04-08  expires: 2017-04-08  usage: S
[ultimate] (1). Peter H. Ezetta

gpg> adduid
Real name: Peter H. Ezetta
Email address: protocall7@gmail.com
Comment:
You selected this USER-ID:
    "Peter H. Ezetta "

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o

You need a passphrase to unlock the secret key for
user: "Peter H. Ezetta "
4096-bit RSA key, ID DDC547B9, created 2016-04-08


pub  4096R/DDC547B9  created: 2016-04-08  expires: 2020-04-07  usage: C
                     trust: ultimate      validity: ultimate
sub  4096R/3BCD5DA0  created: 2016-04-08  expires: 2017-04-08  usage: E
sub  4096R/A5FA0D33  created: 2016-04-08  expires: 2017-04-08  usage: S
[ultimate] (1)  Peter H. Ezetta
[ unknown] (2). Peter H. Ezetta

gpg> save


Now that the key has been generated on the USB stick, I create a revocation certificate just in case the key is lost of compromised.  This certificate should be closely guarded, as it will render the key useless, however you should maintain more than one copy of it in case it is necessary to use it.  A paper copy is recommended.

gpg --output /Volumes/UNTITLED\ 1/86F22317-revocation.asc --home /Volumes/UNTITLED\ 1 --gen-revoke protocall7@sdf.org
gpg: WARNING: unsafe permissions on homedir `/Volumes/UNTITLED\ 1'

sec  4096R/DDC547B9 2016-04-08 Peter H. Ezetta

Create a revocation certificate for this key? (y/N) y
Please select the reason for the revocation:
  0 = No reason specified
  1 = Key has been compromised
  2 = Key is superseded
  3 = Key is no longer used
  Q = Cancel
(Probably you want to select 1 here)
Your decision? 0
Enter an optional description; end it with an empty line:
> Revocation certificate generated at time of key creation.  If this certificate is in use, it is likely I have lost access to the secret key.
>
Reason for revocation: No reason specified
Revocation certificate generated at time of key creation.  If this certificate is in use, it is likely I have lost access to the secret key.
Is this okay? (y/N) y

You need a passphrase to unlock the secret key for
user: "Peter H. Ezetta "
4096-bit RSA key, ID DDC547B9, created 2016-04-08

ASCII armored output forced.
Revocation certificate created.

Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable.  But have some caution:  The print system of
your machine might store the data and make it available to others!


The revocation certificate and key-pair exist only on the USB stick.  At this point, we need to import the secret subkeys to the local machine (leaving the secret key on the USB stick for safe keeping).  This can be done by exporting the secret subkeys, then importing them without --homedir:

$ gpg --homedir /Volumes/UNTITLED\ 1 --export-secret-subkeys protocall7@sdf.org > /Volumes/UNTITLED\ 1/secretsubkeys.gpg
$ gpg --homedir /Volumes/UNTITLED\ 1 --export protocall7@sdf.org > /Volumes/UNTITLED\ 1/publickey.gpg
$ gpg --import /Volumes/UNTITLED\ 1/publickey.gpg
gpg: key DDC547B9: public key "Peter H. Ezetta " imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)

$ gpg --import /Volumes/UNTITLED\ 1/secretsubkeys.gpg
gpg: key DDC547B9: secret key imported
gpg: key DDC547B9: "Peter H. Ezetta " not changed
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

$ gpg -K
/Users/peter.ezetta/.gnupg/secring.gpg
--------------------------------------

sec#  4096R/DDC547B9 2016-04-08 [expires: 2020-04-07]
uid                  Peter H. Ezetta
uid                  Peter H. Ezetta
ssb   4096R/3BCD5DA0 2016-04-08
ssb   4096R/A5FA0D33 2016-04-08


From this, we see that the local copy of GPG has our secret subkeys in it's ring, but the secret key itself is missing (this is evidenced by the # after 'sec').  With the subkeys in place, encryption and signing still work just fine, but if a key needs to be created, revoked, or signed, the USB stick will have to be mounted up and --homedir will need to be added to gpg to point into the backup copy.  For demonstration purposes, here is the secret key output using the USB stick.  Notice that the secret key is present on this one:

$ gpg --homedir /Volumes/UNTITLED\ 1 -K
gpg: WARNING: unsafe permissions on homedir `
/Volumes/UNTITLED\ 1'
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2020-04-07
/Volumes/UNTITLED\ 1/secring.gpg
----------------------
sec   4096R/DDC547B9 2016-04-08 [expires: 2020-04-07]
uid                  Peter H. Ezetta
uid                  Peter H. Ezetta
ssb   4096R/3BCD5DA0 2016-04-08
ssb   4096R/A5FA0D33 2016-04-08


In the next part of this series, I will discuss the web of trust and key signing, then introduce Pass, "the UNIX default password manager".  Pass is backed by GPG encryption to keep your passwords safe, so now that keys have been set up, we can start using it.

Interesting Reading:

The GNU Privacy Handbook
Into The Void - Creating a new key with subkeys
Debian Wiki - Subkeys

Tuesday, June 16, 2015

PZ80emu - The PZ80 Machine Emulator

While I was messing about with the PZ80 schematics, I realized that I really needed an environment where I could write and run test code for the ROM monitor before I went burning EEPROMs.  I searched around for a few days for a suitable machine emulator, but ran into severe bugs with those that I found that weren't tailor made as CP/M emulators.

While I was searching around, I came across the website of Marat Fayzullin, who wrote a fantastic HOWTO on writing computer emulators:

http://fms.komkon.org/EMUL8/HOWTO.html

The PZ80emu is far from complete, but so far is able to load ROMs compiled by z80asm on my Mac.  It executes them quite well from what I tell, as long as I don't use any of the instructions I haven't implemented yet.  I have also implemented a very basic NCurses interface, mostly because I've never coded with NCurses before and thought it would be fun.

The code is most definitely alpha, and is incomplete, but anyone interested in hacking on what I've got so far is more than welcome.  I will certainly keep the Git repository up to date as I hack on the code, and will gladly accept pull requests.

https://github.com/protoCall7/PZ80emu

Sunday, June 14, 2015

PZ80 - Taking Another Step Back

After re-designing the bus buffering on the Z80, the project kind of stalled for me.  I ordered some parts now and again, and tweaked the schematics, but didn't make a whole lot of progress.

Feeling that this was an unacceptable state of affairs, I decided to take a step backwards and simplify my circuit.  What I would up with was the Z80 being fed with power from my bench supply, the entire data bus pulled low with 1K resistors, a few pull-up/down resistors on the control lines, and the oscillator.  Once that was set up, I connected my handy-dandy OpenBench Logic Analyzer up to the first 7 bits of the address bus, and to the clock signal, and fired everything up:



Admittedly, it didn't look like that on the first shot, but after some troubleshooting, it turned out to be user error in the configuration of the logic analyzer, not in the board itself.

The pattern above is caused by the address bus doing a binary countup.  The Z80 instruction set has the NOP instruction as 0x00.  By pulling the entire data bus low and resetting the CPU, the machine will start at address 0x0000, read a "NOP" from the data bus, increment the counter to 0x0001, read another "NOP", and repeat.  Since the current address in the program counter is displayed in binary on the address bus, the logic analyzer displays the above pattern when the board runs.

As far as farther incarnations of the design, I have decided to temporarily build a "MK1" type design, utilizing 32k of ROM and 32k of RAM.  It will use an SIO and a MAX-232 for serial communication, and I would like to work on implementing an IDE interface using CF storage (but this might wait).  This design won't be adequate to run CP/M, but will give me a working platform to start developing the ROM monitor, which will be an integral part of boot loading CP/M in the MK2 design, which would integrate a memory bank switching scheme to swap the ROM out for a 32k RAM chip as a part of the CP/M load process.

I haven't yet decided whether to implement the Z80-CTC for interrupt control + Z80-SIO timing in the MK1 design, or just use another full can oscillator to give a fixed serial baud rate, but I will be going with one of those two methods.

In the mean time, I have been working on putting together a machine emulator in C, as I haven't found anything suitable to write and debug my ROM monitor with, but that's a subject for another post.

One last note, I finally decided on a name - The PZ80!