<?xml version="1.0"?>

<rss version="2.0">
  <channel>
    <title>Imperialviolet</title>
    <link>http://www.imperialviolet.org</link>
    <description>Adam Langley's Weblog</description>
    <language>en-us</language>
    <lastBuildDate>Thu, 01 May 2008 04:55:39 BST</lastBuildDate>
<item><link>http://imperialviolet.org/page30.html#e588</link><pubDate>Thu, 01 May 2008 03:55:31 GMT</pubDate><title>Entry 588</title><link>http://imperialviolet.org/page30.html#e588</link><description>
&lt;p&gt;I've updated the patches linked to in the last post with today's work. Both
sides now end up with the same shared key (and not just because they got the
same private key from lack of entropy like before). That took some fun tracking
down of bugs.&lt;/p&gt;

&lt;p&gt;Also, packets are now HMAC-MD5'ed with the shared key, and invalid packets
are dropped. That also took far longer than expected. I ended up using the MD5
implementation from the CIFS filesystem because the kernel's crypto library is
just plain terrible. It's also totally undocumented but, from what I can see,
you can't lookup an algorithm without taking a semaphore, and that requires
that you be able to sleep. I almost think I must be missing something because
that's dumber than the bastard offspring of Randy Hickey and Jade Goodie.&lt;/p&gt;

&lt;p&gt;But there we go. Encryption (with Salsa20) to come next Wednesday.&lt;/p&gt;
</description></item><item><link>http://imperialviolet.org/page30.html#e587</link><pubDate>Thu, 24 Apr 2008 03:20:41 GMT</pubDate><title>Entry 587</title><link>http://imperialviolet.org/page30.html#e587</link><description>
&lt;h6&gt;First Obsfucated TCP patches&lt;/h6&gt;

&lt;p&gt;After a day of kernel hacking, I have a few patches which, together, make a
start towards implementing ObsTCP.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add support for Jumbo TCP options, as documented &lt;a href=&quot;/binary/jumbo-tcp-options.html&quot;&gt;here&lt;/a&gt;: &lt;a href=&quot;/binary/obstcp/tcp-jumbo-options&quot;&gt;&lt;tt&gt;tcp-jumbo-options.patch&lt;/tt&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Add curve25519: &lt;a href=&quot;/binary/obstcp/curve25519&quot;&gt;&lt;tt&gt;curve25519.patch&lt;/tt&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Some ObsTCP work: &lt;a href=&quot;/binary/obstcp/tcp-obsfucated-tcp&quot;&gt;&lt;tt&gt;tcp-obsfucated-tcp.patch&lt;/tt&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the moment, it will advertise ObsTCP on all connections and, if you have
two kernels which support it, you'll get a shared key setup. At the moment, the
private key is generated at boot time and since the host doesn't have any
entropy then, it's always the same. So I'll have to do something special there.
Also, I've a problem where the ACK with the connecting host's public key can
get lost. Since ACKs aren't ACKed, this can be a real pain. I think I need to
include it in every transmitted packet until (yet another) option signifies
that it's been received.&lt;/p&gt;
</description></item><item><link>http://imperialviolet.org/page30.html#e586</link><pubDate>Wed, 16 Apr 2008 22:13:37 GMT</pubDate><title>Entry 586</title><link>http://imperialviolet.org/page30.html#e586</link><description>
&lt;p&gt;After the last post explained why small curves aren't good enough for obsfucated TCP, I decided that, since I'm going to have to do some damage to the TCP header to get a bigger public key in there anyway, I might as well go the whole way and use &lt;a href=&quot;http://cr.yp.to/ecdh.html&quot;&gt;curve25519&lt;/a&gt;, by djb. Now, djb has forgotten more about elliptic curves than I'll ever know and I feel much happier using a curve that's been designed by him. As you can probably guess from the name, it's a curve over 2&lt;sup&gt;255&lt;/sup&gt;-19 - a prime. So the public keys are 32 bytes long.&lt;/p&gt;

&lt;p&gt;In order to get that much public key material into a TCP header, here's my proposed hack: &lt;a href=&quot;/binary/jumbo-tcp-options.html&quot;&gt;Jumbo TCP options&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;djb's sample implementation of curve25519 is written in a special assembly language called &lt;a href=&quot;http://cr.yp.to/qhasm.html&quot;&gt;qhasm&lt;/a&gt;. Sadly, it's so alpha that he's not actually released it. So the sample implementation is for ia32 only, uses the floating point registers and has 5100 lines of uncommented assembly. It is, however, freaking quick.&lt;/p&gt;

&lt;p&gt;However, since I have kernel-space in mind for this I've written a C implementation. It's about 1/3 the speed (and I've not really tried to optimise it yet), doesn't use any floating point (since kernel-space doesn't have easy access to the fp registers in Linux) and fuzz testing seems to indicate that it's correct. (At least, it's giving the same answers as djb's code.)&lt;/p&gt;

&lt;p&gt;Next step: hacking up the kernel. (And I thought the elliptic curve maths was hard enough.)&lt;/p&gt;
</description></item><item><link>http://imperialviolet.org/page30.html#e585</link><pubDate>Wed, 09 Apr 2008 05:14:54 GMT</pubDate><title>Entry 585</title><link>http://imperialviolet.org/page30.html#e585</link><description>
&lt;h6&gt;Elliptic curves don't work either&lt;/h6&gt;

&lt;p&gt;(For context, see &lt;a href=&quot;http://www.imperialviolet.org/page30.html#e580&quot;&gt;my previous post on OTCP&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;In any Diffie-Hellman exchange based on elliptic curves, we have
&lt;i&gt;Q=aP&lt;/i&gt; where &lt;i&gt;P&lt;/i&gt; and &lt;i&gt;Q&lt;/i&gt; are points on an elliptic curve. The
operation of multiplying a point and a scalar is well defined, but unimportant
here. The problem facing the attacker is, given &lt;i&gt;Q&lt;/i&gt; and &lt;i&gt;P&lt;/i&gt;, find
&lt;i&gt;a&lt;/i&gt;. If they can do that, we're sunk.&lt;/p&gt;

&lt;p&gt;If you could find a pair of numbers such that: &lt;i&gt;cP + dQ = eP + fQ&lt;/i&gt; then
you're done because: &lt;i&gt;(c-e)P = (f-d)Q = (f-d)aP&lt;/i&gt;, then &lt;i&gt;a =
(c-e)/(f-d) &lt;i&gt;mod&lt;/i&gt; n&lt;/i&gt;, where &lt;i&gt;n&lt;/i&gt; is the size of the field
underlying the curve.&lt;/p&gt;

&lt;p&gt;Finding such a point by picking random examples is never going to work
because of the storage requirements. However, if you define a step function
which takes a pair &lt;i&gt;(c, d)&lt;/i&gt; and produces a new pair &lt;i&gt;(c', d')&lt;/i&gt; you
have defined a cycle through the search space. (It must be a cycle because the
search space is finite. At some point you must hit a previous state and loop
forever.) Now you can use &lt;a
href=&quot;http://en.wikipedia.org/wiki/Cycle_detection&quot;&gt;Floyd's cycle finding
algorithm&lt;/a&gt; to find a collision with constant space. This is an &amp;radic;n
algorithm for breaking this problem and is well known as Pollard's rho method.&lt;/p&gt;

&lt;p&gt;Now, if you have many of these problems you get a big speed up by using some
storage. Assume that you do the legwork to solve an instance of the problem and
that you record some fraction of the points that you evaluated. (How you choose
the points isn't important so long as it's a function of the point; say pick
all points where the first &lt;i&gt;m&lt;/i&gt; bits are zero.)&lt;/p&gt;

&lt;p&gt;Now, future attempts to break the problem can collide with one of the
previous points. If you find &lt;i&gt;cP + dQ = eP + fR&lt;/i&gt; (note that P is a
constant of the elliptic curve system) and also that &lt;i&gt;R = bP&lt;/i&gt; (because we
solved this instance previously) then &lt;i&gt;cP + dQ = cP + adP = (e+fb)P&lt;/i&gt; and
so &lt;i&gt;(c-(e+fb)) / d = a&lt;/i&gt; (and we know all the values on the left-hand side).&lt;/p&gt;

&lt;p&gt;Now, 2&lt;sup&gt;112&lt;/sup&gt; (14 bytes) is about as big an elliptic curve point as we can fit
in a TCP header. The maximum options payload is 40 bytes, of which 20 are
already taken up in modern TCP stacks. We need 2 bytes of fluff per option and,
unless we want this to be the last TCP header ever, we need to leave at least 4
bytes. That's where the 14 byte limit comes from.&lt;/p&gt;

&lt;p&gt;We give the attacker 2&lt;sup&gt;50&lt;/sup&gt; bytes of space.  I believe that
each point will take 3*14 bytes of space for the (c,d,Y) triple, where
&lt;i&gt;Y = cP+dQ&lt;/i&gt;. Thus they can store 2&lt;sup&gt;44&lt;/sup&gt; distinguished points. Thus
one in 2&lt;sup&gt;56-44=12&lt;/sup&gt; points are distinguished. Additionally, generating those
2&lt;sup&gt;44&lt;/sup&gt; points isn't that hard, computationally. This suggests that an
attacker can find a collision in only 2&lt;sup&gt;12&lt;/sup&gt; iterations., or about
2&lt;sup&gt;13&lt;/sup&gt; field multiplications.&lt;/p&gt;

&lt;p&gt;So, again, a reasonable attacker can break our crypto in real time.&lt;/p&gt;

&lt;p&gt;This scheme becomes much harder to sell if we have to do evil things to the
TCP header in order to make it work.&lt;/p&gt;
</description></item><item><link>http://imperialviolet.org/page30.html#e584</link><pubDate>Thu, 20 Mar 2008 17:25:04 GMT</pubDate><title>Entry 584</title><link>http://imperialviolet.org/page30.html#e584</link><description>
&lt;p&gt;If you've been wondering what I'm up to at work, we now have a &lt;a href=&quot;http://rechargeit.blogspot.com&quot;&gt;public blog for the RechargeIt project&lt;/a&gt;.&lt;/p&gt;
</description></item><item><link>http://imperialviolet.org/page30.html#e583</link><pubDate>Wed, 19 Mar 2008 22:05:56 GMT</pubDate><title>Entry 583</title><link>http://imperialviolet.org/page30.html#e583</link><description>
&lt;p&gt;How sad: from reading &lt;a href=&quot;http://www.oracle.com/technology/documentation/berkeley-db/db/ref/rep/partition.html&quot;&gt;the sleepcat documentation on network partitions&lt;/a&gt;, it's clear that BDB uses a broken replication system (i.e. not Paxos). That's a shame because I was hoping to use it.&lt;/p&gt;
</description></item><item><link>http://imperialviolet.org/page30.html#e582</link><pubDate>Wed, 19 Mar 2008 03:41:19 GMT</pubDate><title>Entry 582</title><link>http://imperialviolet.org/page30.html#e582</link><description>
&lt;p&gt;Yahoo now has &lt;a href=&quot;http://openid.yahoo.com&quot;&gt;OpenID&lt;/a&gt; for all its accounts, which is great. Wonderful in fact. OpenID is a good thing for many authentication needs on the Internet and will make the world a better place.&lt;/p&gt;

&lt;p&gt;However,...&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;SHA256 isn't supported, only SHA1. It's true that the standard doesn't require it, but this still gets you lots of crapness points.&lt;/li&gt;
  &lt;li&gt;The &lt;tt&gt;return_to&lt;/tt&gt; is filtered. Probably someone here had good intentions, but I can redirect a browser to any URL, so filtering the &lt;tt&gt;return_to&lt;/tt&gt; is pointless and overly restrictive. Specifically, it appears that:
    &lt;ul&gt;
	  &lt;li&gt;You can't have a port number in the host&lt;/li&gt;
	  &lt;li&gt;You can't have an IP address for a host&lt;/li&gt;
	  &lt;li&gt;You can't have a single element hostname (like &lt;tt&gt;localhost&lt;/tt&gt;)&lt;/li
    &lt;/ul&gt;So, more crapness points for Yahoo.&lt;/li&gt;&lt;/ul&gt;
</description></item><item><link>http://imperialviolet.org/page30.html#e581</link><pubDate>Sat, 15 Mar 2008 22:04:10 GMT</pubDate><title>Entry 581</title><link>http://imperialviolet.org/page30.html#e581</link><description>
&lt;h6&gt;How good is a 64-bit DH exchange?&lt;/h6&gt;

&lt;p&gt;In my last post, I suggested that a register based modexp for 64-bit numbers could run at about 500K ops/sec. Well, I wrote one and got 450K ops/sec on an older Core2. (That's with gcc -O3, but no tuning of the code. Plus, I don't know the standard algorithm for 128-bit modulus using 64-bit operations, so I wrote my own, which is almost certainly suboptimal.). Roughly that's 2&lt;sup&gt;20&lt;/sup&gt; ops/s, so a brute force solution of 64-bits would take about 2&lt;sup&gt;42&lt;/sup&gt; seconds, which is more than enough for us.&lt;/p&gt;

&lt;p&gt;However, there are much better solutions to the discrete log problem than that. Here I'm only dealing with groups of prime order. There are &lt;i&gt;very&lt;/i&gt; good solutions for groups of order 2&lt;sup&gt;n&lt;/sup&gt;, but DH uses prime order groups only.&lt;/p&gt;

&lt;p&gt;The best information I found on this are a &lt;a href=&quot;http://cr.yp.to/talks/2007.09.03-2/slides.pdf&quot;&gt;set of slides by djb&lt;/a&gt;. However, they are a little sparse (since they are slides after all). Quick summary:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Brute force parallelises perfectly. An FPGA chip could do 2&lt;sup&gt;30&lt;/sup&gt; modexps per second. An array of really good ones could push that upwards of 2&lt;sup&gt;40&lt;/sup&gt; modexps/sec.&lt;/li&gt;
  &lt;li&gt;Breaking &lt;i&gt;n&lt;/i&gt; Diffie-Hellmans isn't much harder than breaking one of them when using brute force. Since you can look for collisions against all &lt;i&gt;n&lt;/i&gt; public keys at once. If you were a sniffer trying to sniff hundreds of connections per second, that's actually a big advantage. That could give up an amortised benefit equal to 2&lt;sup&gt;10&lt;/sup&gt; or more.&lt;/li&gt;
  &lt;li&gt;You can use &quot;random self reduction&quot; to &quot;split&quot; a problem into many problems and solving any of them they breaks the original problem. Combine this with the previous point and you can speed up the breaking of a single problem.&lt;/li&gt;
  &lt;li&gt;If you figure out the optimal number of subproblems to &quot;split&quot; the original problem into you have the &quot;giant step, baby step&quot; algorithm which takes only about 2&amp;radic;n modexps to break (where n is 64 in our case).&lt;/li&gt;
  &lt;li&gt;Now things are getting complex, so I'm just going to include the results: Pollard's rho method lets us break 64-bits in 2&lt;sup&gt;32&lt;/sup&gt; modexps.&lt;/li&gt;
  &lt;li&gt;The Pohlig-Hellman method is even better, but you can choose a safe prime as your group order to stop it. (A safe prime, p, is such that (p-1)/2 is also prime.)&lt;/li&gt;
  &lt;li&gt;The &quot;index calculus&quot; method uses lots of precomputation against the group order to find specific solutions in that group very quickly. I must admit that I'm a little shaky on how index calculus works, but I've found one empirical result where a Matlab solution was breaking 64-bit discrete logs in &lt; 1 minute, &lt;i&gt;including the precomputation&lt;/i&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, attacks against discrete log in prime order groups are a lot stronger that I suspected. The index calculus method, esp, seems be a killer against 64-bit DH exchanges providing any sort of security. Since we don't have the time (on the server) or the space (in the TCP options) to include a unique group for each exchange, the precomputation advantage means that it's very possible for a sniffer to be breaking these handshakes in real time.&lt;/p&gt;

&lt;p&gt;Damm.&lt;/p&gt;

&lt;p&gt;So it would appear that we need larger key sizes and, possibly elliptic curve based systems (the EC systems, in general, can't be attacked with index calculus based methods). RFC 2385 suggests that 16 bytes in a TCP header is about as much as we would want to add (they are talking about SYN packets, which we don't need to put public values in, but the absolute max is 36 bytes.), which gives us 128-bit public values. Looks like I need to read up on EC systems.&lt;/p&gt;
</description></item><item><link>http://imperialviolet.org/page29.html#e580</link><pubDate>Wed, 12 Mar 2008 00:14:52 GMT</pubDate><title>Entry 580</title><link>http://imperialviolet.org/page29.html#e580</link><description>
&lt;h6&gt;OTCP - Obfuscated TCP&lt;/h6&gt;

&lt;p&gt;Like open SMTP relays, TCP was developed in a kinder, gentler time. With &lt;a
href=&quot;http://arstechnica.com/news.ars/post/20080213-comcast-discloses-network-management-practices.html&quot;&gt;Comcast
forging RST packets to disrupt connections&lt;/a&gt; and &lt;a
href=&quot;http://arstechnica.com/news.ars/post/20080309-bad-phorm-uk-isps-to-sell-clickstream-data-to-advertisers.html&quot;&gt;UK
ISPs looking to trawl the clickstreams of a nation and sell them&lt;/a&gt; (not to
mention AT&amp;T copying their backbone to the NSA) it's time that TCP got a little
more paranoid.&lt;/p&gt;

&lt;p&gt;The 'correct' solutions are something along the lines of &lt;a
href=&quot;http://en.wikipedia.org/wiki/IPsec&quot;&gt;IPSec&lt;/a&gt;, but there's no reason to
suspect that anyone is going to start using that in droves any time soon.
Application level crypto (TLS, SSH etc) is the correct solution for protecting
the contents of packets (which would stop the clickstream harvesting style of
attacks), but cannot protect the TCP layer (and HTTPS is still not the default
for websites).&lt;/p&gt;

&lt;p&gt;An opportunistic obfuscation layer, on by default, would start to address this.
By making it transparent to use, it stands a chance of getting some small
fraction of traffic to use it. If it were included in Linux distribution
kernels we might hope to see it in the wild after a year or so. In certain
sectors (BitTorrent users and trackers) we might see it much sooner.&lt;/p&gt;

&lt;p&gt;Our attacker has a couple of weaknesses:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Their sniffers are in parallel with their backbone for good reason: if
  the sniffers fail or cannot keep up with the traffic it's not a big deal.
  This means that they are limited to observing and injecting traffic. Moving
  inline (to alter traffic) would be very expensive.&lt;/li&gt;
  &lt;li&gt;Legally, altering traffic seems to be much more sensitive than filtering
  it. Much of Comcast's statements about their RST injection have been
  stressing that it's limiting, not forging nor intercepting (however
  technically false that might be).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that in mind I'm going to suggest the following:&lt;/p&gt;

&lt;p&gt;SYN packets from OTCP hosts include an empty TCP option advertising their
support. OTCP servers, upon seeing the offer in the RST packet, generate a
random 64-bit number (n), less than a globally known prime and return 2^n mod p
in another TCP option in the SYN,ACK. The client performs the end of a DH
handshake and includes its random number in a third option in the next packet
to the server.&lt;/p&gt;

&lt;p&gt;The two hosts now have a shared key which they can use to MAC and encrypt
each packet in the subsequent connection (the MAC will be carried in a TCP
option). The MAC function includes the TCP header and payload, except the
source and destination port numbers. The encryption only covers the TCP
payload, not the IP nor TCP packet.&lt;/p&gt;

&lt;p&gt;The hash function and cipher need to very fast and just strong enough;
the key is only 64-bits. MD4 for the hash function and AES128 for the cipher,
say. (&lt;a href=&quot;http://www.cryptopp.com/benchmarks.html&quot;&gt;benchmarks for
different functions from the Crypto++ library&lt;/a&gt;). I suspect that the cipher
needs to be a block cipher because packets get retransmitted and reordered. A
block cipher in CTR mode based on the sequence number seems to be the best way
to deal with this.&lt;/p&gt;

&lt;p&gt;A getsockopt interface would allow userland to find out if a given
connection is OTCP, and to get the shared key.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Q: Can't this be broken by man-in-the-middle attacks?&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Yes. However, note that this would require interception of traffic which is
much more costly than sniffers in parallel and legally more troublesome for the
attacker. Additionally, userland crypto protocols could be extended to include the
shared secret in their certified handshakes, thus giving them MITM-proof
security which includes the TCP layer.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Q: Isn't the key size very small?&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Yes. However, even if the key could be brute forced in 10 seconds; that's
still far too much work for a device which is monitoring hundreds or thousands
of connections per second.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Q: Doesn't this break NATs&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;NATs rewrite the IP addresses and port numbers in the packets, which we
don't include in our MAC protection, so everything should work. If the NAT
happens to rebuild the whole packet, the OTCP offer in the SYN packet will be
removed. In this case we loose OTCP but, most importantly, we don't break any
users.&lt;/p&gt;

&lt;p&gt;NATs which monitor the application level and try to rewrite IP address in
there will be broken by this. However, the number of protocols which do this is
small and clients may be configured by default not to offer OTCP when the
destination port number matches one of these protocols (IRC and FTP spring to
mind). This is a hack, but the downside to users of OTCP must be as small as possible.

&lt;p&gt;&lt;i&gt;Q: So can't I break this by filtering the offer from the SYN packet?&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Yes. Application level protocols could be extended to sense this downgrade
attack and stop working, but mostly see the points above: it's much more
expensive to do this since it needs to be done in the router and it's legally
more troublesome for the attacker.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Q: Won't this take too much time?&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;It's additional CPU load, certainly. The Crypto++ and OpenSSL benchmarks
suggest that a full core should be able to handle this at 1 Gbps. Most servers
don't see anything like that traffic. Maybe more concerning is the DDoS
possibility of using OTCP to force a server to do a 64-bit modexp with a
single, unauthenticated packet. A very quick knock-up using the OpenSSL BN
library suggests that a single Core2@2.33GHz can do about 50000 random
generations and modexps per second. Since the keys are so small, I expect that
a tuned implementation (using registers, not bigints) would be about 10x
faster. You probably run out of bandwidth from all the SYNs before 500,000 SYNs
per second second maxes a single core (it's about 37MB/s). So SYN floods
shouldn't be any more of a problem.

&lt;p&gt;&lt;i&gt;Q: What about my high-performance network?&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;I suggest that offering OTCP be disabled by default for private address
ranges. Also, distributions probably won't turn it on for their &quot;server&quot;
releases. If all else fails, it'll be a sysctl.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Q: But then I'm wasting CPU time and packet space whenever I'm running
SSH or HTTPS&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Right. Userland can turn off OTCP using a sockopt if it wishes, or it could
just not enable itself for the default destination ports which these protocols
use. (Again, that would be an ugly intrusion of default port numbers into the
kernel, but this idea wasn't that beautiful to begin with.)

&lt;p&gt;&lt;i&gt;Q: So, what's the plan?&lt;/i&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Write a patch&lt;/li&gt;
  &lt;li&gt;Get it in the mainline&lt;/li&gt;
  &lt;li&gt;Badger distributions to compile it in with server support and client side off by default.&lt;/li&gt;
  &lt;li&gt;In time, get the client side offers turned on by default for &quot;desktop&quot; distributions&lt;/li&gt;
  &lt;li&gt;Save Internet&lt;/li&gt;
&lt;/ul&gt;
</description></item><item><link>http://imperialviolet.org/page29.html#e579</link><pubDate>Wed, 27 Feb 2008 23:45:20 GMT</pubDate><title>Entry 579</title><link>http://imperialviolet.org/page29.html#e579</link><description>
&lt;h6&gt;Keyspan USB serial dongle drivers for amd64 Ubuntu 7.10&lt;/h6&gt;

&lt;p&gt;Ubuntu doesn't ship with this driver, but it's useful: &lt;a href=&quot;binary/keyspan.ko&quot;&gt;&lt;tt&gt;keyspan.ko&lt;/tt&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To install, copy to &lt;tt&gt;/lib/modules/2.6.22-14-generic/kernel/drivers/usb/serial&lt;/tt&gt; and &lt;tt&gt;depmod -a &amp;&amp; modprobe keyspan&lt;/tt&gt; (as root).&lt;/p&gt;
</description></item></channel></rss>